├── .gitattributes ├── .gitignore ├── README.md ├── build.gradle ├── circle.yml ├── common ├── .gitignore ├── build.gradle └── src │ └── main │ └── java │ └── microservices4vaadin │ └── userevents │ ├── AbstractEvent.java │ └── UserCreatedEvent.java ├── doc ├── Architecture.png ├── landing_page.png ├── rancher_stack_graph.png └── vaadin_ui.png ├── docker-compose.yml ├── docker-compose_all.yml ├── docker-db-dump └── create-databases.sql ├── gradle ├── docker.gradle ├── jacoco.gradle ├── jacocoAll.gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── microservices ├── authserver │ ├── .gitignore │ ├── build.gradle │ ├── docker-compose.yml │ ├── docker-entrypoint.sh │ └── src │ │ ├── main │ │ ├── java │ │ │ └── microservices4vaadin │ │ │ │ ├── auth │ │ │ │ ├── AcmeUser.java │ │ │ │ ├── AcmeUserDetails.java │ │ │ │ ├── Authorities.java │ │ │ │ └── Authority.java │ │ │ │ └── authserver │ │ │ │ ├── AuthserverApplication.java │ │ │ │ ├── configuration │ │ │ │ ├── CustomAuthenticationSuccessHandler.java │ │ │ │ ├── RestClientConfiguration.java │ │ │ │ ├── SessionConfiguration.java │ │ │ │ ├── SessionSerializer.java │ │ │ │ └── WebSecurityConfiguration.java │ │ │ │ ├── controller │ │ │ │ ├── CredentialUpdateResource.java │ │ │ │ ├── RegistrationController.java │ │ │ │ └── UserController.java │ │ │ │ ├── exception │ │ │ │ ├── UserNotActivatedException.java │ │ │ │ ├── UserNotFoundException.java │ │ │ │ └── WrongOldPasswordException.java │ │ │ │ ├── repository │ │ │ │ ├── AuthorityRepository.java │ │ │ │ └── UserRepository.java │ │ │ │ ├── rest │ │ │ │ └── controller │ │ │ │ │ ├── UserEventController.java │ │ │ │ │ └── util │ │ │ │ │ └── RestUtils.java │ │ │ │ ├── service │ │ │ │ ├── AcmeUserDetailsService.java │ │ │ │ ├── ActivationService.java │ │ │ │ ├── EmailService.java │ │ │ │ ├── EmailServiceImpl.java │ │ │ │ ├── FreemarkerEmailService.java │ │ │ │ ├── FreemarkerEmailServiceImpl.java │ │ │ │ ├── Registration.java │ │ │ │ ├── RegistrationService.java │ │ │ │ └── RegistrationServiceImpl.java │ │ │ │ └── util │ │ │ │ ├── ConstantsUtil.java │ │ │ │ ├── RandomUtil.java │ │ │ │ └── SecurityUtil.java │ │ └── resources │ │ │ ├── application.yml │ │ │ ├── bootstrap.yml │ │ │ ├── db │ │ │ └── migration │ │ │ │ ├── V000001__init.sql │ │ │ │ └── V000002__remove_user_details.sql │ │ │ └── keystore.jks │ │ └── test │ │ ├── java │ │ └── microservices4vaadin │ │ │ └── authserver │ │ │ ├── ApplicationTests.java │ │ │ └── rest │ │ │ └── BasePersistenceTest.java │ │ └── resources │ │ ├── application-test.yml │ │ ├── lessor_empty_dataset.xml │ │ └── lessor_resource_test_dataset.xml ├── config │ ├── .gitignore │ ├── build.gradle │ └── src │ │ └── main │ │ ├── java │ │ └── microservices4vaadin │ │ │ └── configserver │ │ │ └── ConfigServerApplication.java │ │ └── resources │ │ ├── application.yml │ │ └── bootstrap.yml ├── discovery │ ├── .gitignore │ ├── build.gradle │ ├── docker-entrypoint.sh │ └── src │ │ ├── main │ │ ├── java │ │ │ └── microservices4vaadin │ │ │ │ └── discovery │ │ │ │ └── EurekaApplication.java │ │ └── resources │ │ │ ├── application.yml │ │ │ └── bootstrap.yml │ │ └── test │ │ └── java │ │ └── microservices4vaadin │ │ └── discovery │ │ └── ApplicationTests.java ├── edge │ ├── .gitignore │ ├── build.gradle │ ├── docker-entrypoint.sh │ └── src │ │ ├── main │ │ ├── java │ │ │ └── microservices4vaadin │ │ │ │ ├── auth │ │ │ │ ├── AcmeUser.java │ │ │ │ ├── AcmeUserDetails.java │ │ │ │ └── Authority.java │ │ │ │ └── edge │ │ │ │ ├── CorrectHeadersFilter.java │ │ │ │ ├── ZuulApplication.java │ │ │ │ ├── config │ │ │ │ ├── CORSFilter.java │ │ │ │ ├── CustomAuthenticationEntryPoint.java │ │ │ │ ├── CustomLogoutSuccessHandler.java │ │ │ │ ├── SecurityConfiguration.java │ │ │ │ ├── SessionConfiguration.java │ │ │ │ └── SessionSerializer.java │ │ │ │ └── exception │ │ │ │ ├── UserNotActivatedException.java │ │ │ │ └── UserNotFoundException.java │ │ ├── resources │ │ │ ├── application.yml │ │ │ ├── bootstrap.yml │ │ │ ├── keystore.jks │ │ │ └── static │ │ │ │ ├── empty.html │ │ │ │ ├── index.html │ │ │ │ ├── js │ │ │ │ └── hello.js │ │ │ │ └── login.html │ │ └── wro │ │ │ ├── main.less │ │ │ ├── wro.properties │ │ │ └── wro.xml │ │ └── test │ │ └── java │ │ └── microservices4vaadin │ │ └── edge │ │ └── ApplicationTests.java ├── eventstore │ ├── .gitignore │ ├── build.gradle │ ├── docker-entrypoint.sh │ └── src │ │ ├── main │ │ ├── java │ │ │ └── microservices4vaadin │ │ │ │ └── eventstore │ │ │ │ ├── EventStoreApplication.java │ │ │ │ ├── aggregate │ │ │ │ └── UserAggregate.java │ │ │ │ ├── command │ │ │ │ ├── ActivateUserCommand.java │ │ │ │ ├── CreateUserCommand.java │ │ │ │ └── DeleteUserCommand.java │ │ │ │ ├── configuration │ │ │ │ ├── AxonConfiguration.java │ │ │ │ └── RabbitConfiguration.java │ │ │ │ └── controller │ │ │ │ └── UserEventController.java │ │ └── resources │ │ │ ├── application.yml │ │ │ └── bootstrap.yml │ │ └── test │ │ └── java │ │ └── microservices4vaadin │ │ └── eventstore │ │ ├── aggregate │ │ └── UserAggregateTest.java │ │ └── controller │ │ └── UserEventControllerTest.java ├── frontend │ ├── .gitignore │ ├── build.gradle │ ├── docker-compose.yml │ ├── docker-entrypoint.sh │ ├── launch │ │ └── Lessor frontend (Development).launch │ └── src │ │ ├── main │ │ ├── java │ │ │ ├── microservices4vaadin │ │ │ │ ├── auth │ │ │ │ │ ├── AcmeUser.java │ │ │ │ │ ├── AcmeUserDetails.java │ │ │ │ │ └── Authority.java │ │ │ │ └── frontend │ │ │ │ │ ├── VaadinApplication.java │ │ │ │ │ ├── config │ │ │ │ │ ├── RestClientConfiguration.java │ │ │ │ │ ├── SerializableConfiguration.java │ │ │ │ │ ├── SessionConfiguration.java │ │ │ │ │ └── SessionSerializer.java │ │ │ │ │ ├── rest │ │ │ │ │ ├── controller │ │ │ │ │ │ ├── AbstractRestController.java │ │ │ │ │ │ ├── AcmeUserController.java │ │ │ │ │ │ ├── BookController.java │ │ │ │ │ │ ├── RestUtils.java │ │ │ │ │ │ └── UserServiceController.java │ │ │ │ │ └── resource │ │ │ │ │ │ ├── dto │ │ │ │ │ │ ├── AbstractHateoasEntity.java │ │ │ │ │ │ ├── AbstractPersonDTO.java │ │ │ │ │ │ ├── Book.java │ │ │ │ │ │ └── UserServiceUserDTO.java │ │ │ │ │ │ └── update │ │ │ │ │ │ ├── AbstractPersonUpdateResource.java │ │ │ │ │ │ ├── AcmeUserUpdateResource.java │ │ │ │ │ │ ├── CredentialUpdateResource.java │ │ │ │ │ │ └── UserServiceUserUpdateResource.java │ │ │ │ │ └── ui │ │ │ │ │ ├── BookView.java │ │ │ │ │ ├── HomeView.java │ │ │ │ │ ├── MainView.java │ │ │ │ │ ├── MyMenu.java │ │ │ │ │ ├── MyMenuItemButton.java │ │ │ │ │ ├── MyNavigator.java │ │ │ │ │ ├── MySessionInitListener.java │ │ │ │ │ ├── MyVaadinUI.java │ │ │ │ │ ├── MyVaadinUIServlet.java │ │ │ │ │ ├── MyViewType.java │ │ │ │ │ ├── ProfileWindow.java │ │ │ │ │ └── event │ │ │ │ │ └── MyEvent.java │ │ │ └── org │ │ │ │ └── springframework │ │ │ │ └── session │ │ │ │ └── data │ │ │ │ └── redis │ │ │ │ └── RedisOperationsSessionRepository.java │ │ ├── resources │ │ │ ├── VAADIN │ │ │ │ └── themes │ │ │ │ │ └── microservices4vaadin │ │ │ │ │ ├── images │ │ │ │ │ └── profile-pic-300px.jpg │ │ │ │ │ ├── microservices4vaadin.scss │ │ │ │ │ ├── styles.scss │ │ │ │ │ └── views │ │ │ │ │ └── valo-menu-responsive.scss │ │ │ ├── application.yml │ │ │ ├── bootstrap.yml │ │ │ └── keystore.jks │ │ └── webapp │ │ │ └── META-INF │ │ │ └── context.xml │ │ └── test │ │ └── java │ │ └── microservices4vaadin │ │ └── frontend │ │ └── VaadinApplicationTests.java ├── hystrixdashboard │ ├── .gitignore │ ├── build.gradle │ ├── docker-entrypoint.sh │ └── src │ │ └── main │ │ ├── java │ │ └── microservices4vaadin │ │ │ └── hystrixdashboard │ │ │ └── HystrixDashboardApplication.java │ │ └── resources │ │ ├── application.yml │ │ ├── bootstrap.yml │ │ ├── hystrixdashboard │ │ └── stream │ │ │ └── hystrix.stream │ │ └── log4j.properties ├── turbine │ ├── .gitignore │ ├── build.gradle │ ├── docker-entrypoint.sh │ └── src │ │ └── main │ │ ├── java │ │ └── microservices4vaadin │ │ │ └── turbine │ │ │ └── TurbineApplication.java │ │ └── resources │ │ ├── application.yml │ │ └── bootstrap.yml └── userservice │ ├── .gitignore │ ├── build.gradle │ ├── docker-compose.yml │ ├── docker-entrypoint.sh │ └── src │ ├── main │ ├── java │ │ └── microservices4vaadin │ │ │ └── userservice │ │ │ ├── UserServiceApplication.java │ │ │ ├── configuration │ │ │ ├── AxonConfiguration.java │ │ │ ├── CustomRepositoryConfiguration.java │ │ │ ├── RabbitConfiguration.java │ │ │ └── RestConfiguration.java │ │ │ ├── handler │ │ │ ├── UserEventHandler.java │ │ │ └── bootstrap.yml │ │ │ ├── persistence │ │ │ └── User.java │ │ │ └── repository │ │ │ └── UserRepository.java │ └── resources │ │ ├── application.yml │ │ ├── bootstrap.yml │ │ └── db │ │ └── migration │ │ ├── Readme │ │ ├── V000001__init.sql │ │ └── V000002__remove_auto_incr.sql │ └── test │ ├── java │ └── microservices4vaadin │ │ └── userservice │ │ └── rest │ │ ├── BasePersistenceTest.java │ │ ├── UserResourceIntegrTest.java │ │ └── UserUpdateResource.java │ └── resources │ ├── application-test.yml │ ├── microservices4vaadin_empty_dataset.xml │ └── microservices4vaadin_resource_test_dataset.xml ├── rancher-docker-compose.yml ├── settings.gradle ├── start-all.bat ├── start-all.sh ├── start-dockerBuild.bat ├── start-dockerBuild.sh └── start-dockerPush.sh /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .classpath 2 | .gradle/ 3 | .project 4 | .settings/ 5 | build/ 6 | /bin/ 7 | *.cache 8 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | ext { 3 | coverallsVersion = "2.7.1" 4 | springBootVersion = "1.5.7.RELEASE" 5 | queryDslVersion = "1.0.9" 6 | } 7 | repositories { 8 | mavenCentral() 9 | maven { url "https://plugins.gradle.org/m2/" } 10 | } 11 | dependencies { 12 | classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}") 13 | classpath("gradle.plugin.com.ewerk.gradle.plugins:querydsl-plugin:${queryDslVersion}") 14 | classpath("org.kt3k.gradle.plugin:coveralls-gradle-plugin:${coverallsVersion}") 15 | } 16 | } 17 | 18 | apply plugin: 'java' 19 | 20 | ext { 21 | jUnitVersion = "4.+" 22 | lombokVersion = "1.16.12" 23 | 24 | //docker 25 | dockerRepository = 'klhauser/microservices4vaadin-' 26 | } 27 | 28 | // all subprojects 29 | project(':microservices') { 30 | subprojects { 31 | apply plugin: 'java' 32 | apply plugin: 'idea' 33 | apply plugin: 'org.springframework.boot' 34 | apply plugin: 'maven' 35 | 36 | springBoot { 37 | requiresUnpack = ['com.netflix.eureka:eureka-core','com.netflix.eureka:eureka-client'] 38 | } 39 | 40 | repositories { 41 | mavenLocal() 42 | mavenCentral() 43 | } 44 | 45 | dependencyManagement { 46 | imports { 47 | mavenBom 'org.springframework.cloud:spring-cloud-starter-parent:Dalston.SR4' 48 | } 49 | } 50 | 51 | group = 'microservices4vaadin' 52 | version = '0.0.1-SNAPSHOT' 53 | 54 | sourceCompatibility = 1.8 55 | targetCompatibility = 1.8 56 | 57 | configurations.all { 58 | // check for updates every build 59 | resolutionStrategy.cacheChangingModulesFor 0, 'seconds' 60 | } 61 | 62 | dependencies { 63 | compile("org.springframework.boot:spring-boot-starter-web") 64 | 65 | compile("org.springframework.cloud:spring-cloud-starter-config") 66 | compile("org.springframework.cloud:spring-cloud-starter-eureka") 67 | 68 | compile "org.projectlombok:lombok:${lombokVersion}" 69 | compile("com.google.guava:guava:18.0") 70 | compile("com.jayway.jsonpath:json-path") 71 | 72 | testCompile("org.springframework.boot:spring-boot-starter-test") 73 | testCompile("junit:junit:${jUnitVersion}") 74 | } 75 | repositories { 76 | maven { 77 | url 'https://repo.spring.io/libs-snapshot' 78 | } 79 | } 80 | 81 | jar { 82 | manifest.attributes provider: 'gradle' 83 | } 84 | 85 | apply from: '../../gradle/jacoco.gradle' 86 | apply from: '../../gradle/docker.gradle' 87 | } 88 | } 89 | 90 | if (project != project(':common')) { 91 | apply from: 'gradle/jacocoAll.gradle' 92 | } 93 | 94 | task wrapper(type: Wrapper) { 95 | gradleVersion = '4.2.1' 96 | } 97 | -------------------------------------------------------------------------------- /circle.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | jobs: 3 | build: 4 | machine: 5 | enabled: true 6 | working_directory: ~/microservices4vaadin 7 | steps: 8 | - checkout 9 | - restore_cache: 10 | key: microservices4vaadin-{{ checksum "build.gradle" }} 11 | - run: ./gradlew clean build coveralls 12 | - save_cache: 13 | paths: 14 | - "~/.gradle" 15 | key: microservices4vaadin-{{ checksum "build.gradle" }} 16 | - deploy: 17 | name: Push image to docker hub 18 | command: | 19 | if [ "${CIRCLE_BRANCH}" == "master" ]; then 20 | docker login -u $DOCKER_USER -p $DOCKER_PASS 21 | ./start-dockerPush.sh 22 | fi -------------------------------------------------------------------------------- /common/.gitignore: -------------------------------------------------------------------------------- 1 | /bin/ 2 | -------------------------------------------------------------------------------- /common/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | repositories { 3 | mavenCentral() 4 | } 5 | dependencies { 6 | } 7 | } 8 | 9 | apply plugin: 'java' 10 | 11 | jar { 12 | baseName = 'common' 13 | } 14 | 15 | repositories { 16 | mavenLocal() 17 | mavenCentral() 18 | } 19 | ext { 20 | lombokVersion = "1.16.6" 21 | } 22 | 23 | dependencies { 24 | compile "org.projectlombok:lombok:${lombokVersion}" 25 | } 26 | -------------------------------------------------------------------------------- /common/src/main/java/microservices4vaadin/userevents/AbstractEvent.java: -------------------------------------------------------------------------------- 1 | package microservices4vaadin.userevents; 2 | 3 | import java.io.Serializable; 4 | 5 | import lombok.Getter; 6 | import lombok.Setter; 7 | 8 | @Getter 9 | @Setter 10 | public abstract class AbstractEvent implements Serializable { 11 | 12 | private static final long serialVersionUID = -5858458671150375756L; 13 | 14 | private Long id; 15 | 16 | } 17 | -------------------------------------------------------------------------------- /common/src/main/java/microservices4vaadin/userevents/UserCreatedEvent.java: -------------------------------------------------------------------------------- 1 | package microservices4vaadin.userevents; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | 6 | @Getter 7 | @Setter 8 | public class UserCreatedEvent extends AbstractEvent { 9 | 10 | private static final long serialVersionUID = 8632225327849072369L; 11 | 12 | private String email; 13 | 14 | private String firstName; 15 | 16 | private String lastName; 17 | 18 | } 19 | -------------------------------------------------------------------------------- /doc/Architecture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khauser/microservices4vaadin/05aab5a8ee0484004bd3368184c617c2853c86be/doc/Architecture.png -------------------------------------------------------------------------------- /doc/landing_page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khauser/microservices4vaadin/05aab5a8ee0484004bd3368184c617c2853c86be/doc/landing_page.png -------------------------------------------------------------------------------- /doc/rancher_stack_graph.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khauser/microservices4vaadin/05aab5a8ee0484004bd3368184c617c2853c86be/doc/rancher_stack_graph.png -------------------------------------------------------------------------------- /doc/vaadin_ui.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khauser/microservices4vaadin/05aab5a8ee0484004bd3368184c617c2853c86be/doc/vaadin_ui.png -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '2' 2 | 3 | services: 4 | rabbitmq: 5 | image: rabbitmq:3.5.1 6 | ports: 7 | - "15672:15672" 8 | - "5672:5672" 9 | 10 | redis: 11 | image: redis:4.0.2-alpine 12 | ports: 13 | - "6379:6379" 14 | 15 | mongodb: 16 | image: mongo:3.4.10 17 | ports: 18 | - "27017:27017" 19 | 20 | mysql: 21 | image: mysql:5.7 22 | environment: 23 | - MYSQL_ALLOW_EMPTY_PASSWORD=yes 24 | - MYSQL_USER=root 25 | volumes: # Mount relative path source folder on host to absolute path destination folder on docker container 26 | - './docker-db-dump/:/docker-entrypoint-initdb.d/' 27 | ports: 28 | - "3306:3306" 29 | -------------------------------------------------------------------------------- /docker-compose_all.yml: -------------------------------------------------------------------------------- 1 | version: '2' 2 | 3 | services: 4 | rabbitmq: 5 | image: rabbitmq:3.5.1 6 | ports: 7 | - "15672:15672" 8 | - "5672:5672" 9 | 10 | redis: 11 | image: redis:4.0.2-alpine 12 | ports: 13 | - "6379:6379" 14 | 15 | authserver_mysql: 16 | image: mysql:5.7 17 | environment: 18 | - MYSQL_ALLOW_EMPTY_PASSWORD=yes 19 | - MYSQL_DATABASE=microservice4vaadin_authserverdb 20 | - MYSQL_USER=root 21 | volumes: 22 | - "/data/mysql:/var/lib/mysql" 23 | 24 | configserver: 25 | image: klhauser/microservice4vaadin-config 26 | restart: always 27 | ports: 28 | - "8888:8888" 29 | 30 | discovery: 31 | image: klhauser/microservice4vaadin-discovery 32 | restart: always 33 | ports: 34 | - "8761:8761" 35 | links: 36 | - configserver 37 | 38 | authserver: 39 | image: klhauser/microservice4vaadin-authserver 40 | restart: always 41 | ports: 42 | - "7777:7777" 43 | links: 44 | - authserver_mysql 45 | - discovery 46 | - redis 47 | - configserver 48 | 49 | frontend: 50 | image: klhauser/microservice4vaadin-frontend 51 | restart: always 52 | ports: 53 | - "8081:8081" 54 | links: 55 | - discovery 56 | - redis 57 | - rabbitmq 58 | - configserver 59 | 60 | edge: 61 | image: klhauser/microservice4vaadin-edge 62 | restart: always 63 | ports: 64 | - "8080:8080" 65 | links: 66 | - discovery 67 | - redis 68 | - frontend 69 | - authserver 70 | - configserver 71 | 72 | #hystrixdashboard: 73 | # image: klhauser/microservice4vaadin-hystrixdashboard 74 | # restart: always 75 | # ports: 76 | # - "7979:7979" 77 | # links: 78 | # - discovery 79 | # - configserver 80 | # 81 | #turbine: 82 | # image: klhauser/microservice4vaadin-turbine 83 | # restart: always 84 | # ports: 85 | # - "8989:8989" 86 | # links: 87 | # - configserver 88 | -------------------------------------------------------------------------------- /docker-db-dump/create-databases.sql: -------------------------------------------------------------------------------- 1 | CREATE DATABASE IF NOT EXISTS microservices4vaadin_authserverdb; 2 | CREATE DATABASE IF NOT EXISTS microservices4vaadin_userservicedb; 3 | -------------------------------------------------------------------------------- /gradle/jacoco.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'jacoco' 2 | 3 | jacoco { 4 | toolVersion = "0.7.7+" 5 | } 6 | 7 | tasks.withType(JavaCompile) { 8 | options.encoding = 'UTF-8' 9 | options.compilerArgs << '-Xlint:all' 10 | } 11 | 12 | jacocoTestReport { 13 | group = 'Coverage reports' 14 | description = 'Generates a test coverage report for a project' 15 | 16 | reports { 17 | xml.enabled = true 18 | html.enabled = true 19 | } 20 | } 21 | 22 | tasks.withType(Test) { 23 | if (System.properties.containsKey('debug')) { 24 | jvmArgs '-Xdebug', '-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005' 25 | } 26 | options { 27 | jvmArgs '-XX:SoftRefLRUPolicyMSPerMB=0', '-noverify' 28 | } 29 | if (System.env.'CI') { 30 | maxHeapSize = '512m' 31 | reports.html.enabled = false 32 | } 33 | testLogging { 34 | events 'skipped', 'failed' 35 | exceptionFormat 'full' 36 | showCauses = true 37 | showExceptions = true 38 | showStackTraces = true 39 | } 40 | jacoco { 41 | append = true 42 | destinationFile = file("${rootDir}/build/jacoco/jacocoTest.exec") 43 | classDumpDir = file("${rootDir}/build/jacoco/classpathdumps") 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /gradle/jacocoAll.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.github.kt3k.coveralls' 2 | apply plugin: 'jacoco' 3 | 4 | jacoco { 5 | toolVersion = "0.7.7+" 6 | } 7 | 8 | repositories { 9 | mavenCentral() 10 | } 11 | 12 | // Only report code coverage for projects that are distributed 13 | def publishedProjects = subprojects.findAll { 14 | (it.path != ':common') && (it.path != ':microservices') 15 | } 16 | 17 | task jacocoRootReport(type: JacocoReport, group: 'Coverage reports') { 18 | description = 'Generates an aggregate report from all subprojects' 19 | //dependsOn(publishedProjects.test) 20 | 21 | additionalSourceDirs = files(publishedProjects.sourceSets.main.allSource.srcDirs) 22 | sourceDirectories = files(publishedProjects.sourceSets.main.allSource.srcDirs) 23 | classDirectories = files(publishedProjects.sourceSets.main.output) 24 | executionData = files(publishedProjects.jacocoTestReport.executionData) 25 | 26 | reports { 27 | html.enabled = true // human readable 28 | xml.enabled = true // required by coveralls 29 | } 30 | 31 | doFirst { 32 | executionData = files(executionData.findAll { it.exists() }) 33 | } 34 | 35 | afterEvaluate { 36 | classDirectories = files(classDirectories.files.collect { 37 | fileTree(dir: it, exclude: 'microservices4vaadin/auth/**') 38 | }) 39 | } 40 | } 41 | 42 | coveralls { 43 | sourceDirs = publishedProjects.sourceSets.main.allSource.srcDirs.flatten() 44 | jacocoReportPath = "${buildDir}/reports/jacoco/jacocoRootReport/jacocoRootReport.xml" 45 | } 46 | 47 | tasks.coveralls { 48 | group = 'Coverage reports' 49 | description = 'Uploads the aggregated coverage report to Coveralls' 50 | 51 | dependsOn jacocoRootReport 52 | } 53 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khauser/microservices4vaadin/05aab5a8ee0484004bd3368184c617c2853c86be/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Tue Oct 31 13:09:29 CET 2017 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.2.1-bin.zip 7 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /microservices/authserver/.gitignore: -------------------------------------------------------------------------------- 1 | .classpath 2 | .gradle/ 3 | .project 4 | .settings/ 5 | build/ 6 | /bin/ 7 | *.cache 8 | -------------------------------------------------------------------------------- /microservices/authserver/build.gradle: -------------------------------------------------------------------------------- 1 | jar { 2 | baseName = 'authserver' 3 | version = '0.0.1-SNAPSHOT' 4 | } 5 | 6 | // maybe needed to check integration with other services 7 | //test.dependsOn upDockerCompose 8 | //test << { 9 | // downDockerCompose.execute() 10 | //} 11 | 12 | ext { 13 | hsqlDbVersion = "2.4.0" 14 | dbUnitVersion = "2.5.4" 15 | flywayVersion = "4.0.3" 16 | springTestDbunitVersion = "1.3.0" 17 | 18 | //docker 19 | imageName = dockerRepository + jar.baseName 20 | version = jar.version 21 | dockerBaseImage = 'anapsix/alpine-java:jre8' 22 | dockerExposePort = 7777 23 | } 24 | 25 | dependencies { 26 | compile project(':common') 27 | 28 | compile("org.springframework.boot:spring-boot-starter-hateoas") 29 | 30 | compile("org.springframework.session:spring-session") 31 | compile("org.springframework.boot:spring-boot-starter-data-redis") 32 | 33 | compile("com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.7.4") // used for LocalDate java8 34 | compile("org.jadira.usertype:usertype.extended:5.0.0.GA") // needed for dbunit and hibernate 35 | 36 | compile("org.springframework.boot:spring-boot-starter-security") 37 | compile("org.springframework.security.oauth:spring-security-oauth2") 38 | compile("org.springframework.security:spring-security-jwt") 39 | 40 | compile("org.springframework.boot:spring-boot-starter-freemarker") 41 | 42 | compile("org.springframework.boot:spring-boot-starter-data-jpa") 43 | runtime("mysql:mysql-connector-java") 44 | compile("org.flywaydb:flyway-core:${flywayVersion}"); 45 | 46 | compile("org.apache.commons:commons-lang3:3.0") 47 | compile("javax.mail:mail:1.4.7") 48 | 49 | testCompile("org.hsqldb:hsqldb:${hsqlDbVersion}") 50 | testRuntime("org.hsqldb:hsqldb:${hsqlDbVersion}") 51 | testCompile("org.dbunit:dbunit:${dbUnitVersion}") 52 | testCompile("com.github.springtestdbunit:spring-test-dbunit:${springTestDbunitVersion}") 53 | } 54 | -------------------------------------------------------------------------------- /microservices/authserver/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '2' 2 | 3 | services: 4 | rabbitmq: 5 | image: rabbitmq:3.5.1 6 | 7 | redis: 8 | image: redis:4.0.2-alpine 9 | ports: 10 | - "6379:6379" 11 | 12 | mongodb: 13 | image: mongo:3.4.10 14 | 15 | eventstore: 16 | image: klhauser/microservices4vaadin-eventstore 17 | ports: 18 | - "6666:6666" 19 | links: 20 | - rabbitmq 21 | - mongodb 22 | -------------------------------------------------------------------------------- /microservices/authserver/docker-entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | CONTAINER_IP='http://rancher-metadata.rancher.internal/latest/self/container/primary_ip' 4 | 5 | STATUS_CODE=$(curl --write-out %{http_code} --silent --output /dev/null ${CONTAINER_IP}) 6 | 7 | if [ "$STATUS_CODE" -eq "200" ] ; then 8 | EUREKA_INSTANCE_HOSTNAME=$(curl http://rancher-metadata.rancher.internal/latest/self/container/primary_ip) 9 | echo "Instance hostname: " . $EUREKA_INSTANCE_HOSTNAME 10 | exec java -jar -Djava.security.egd=file:/dev/./urandom -Dspring.profiles.active=docker -Deureka.instance.preferIpAddress=true -Deureka.instance.ipAddress=$EUREKA_INSTANCE_HOSTNAME -Deureka.instance.hostname=$EUREKA_INSTANCE_HOSTNAME /app.jar 11 | else 12 | exec java -jar -Djava.security.egd=file:/dev/./urandom -Dspring.profiles.active=docker /app.jar 13 | fi 14 | -------------------------------------------------------------------------------- /microservices/authserver/src/main/java/microservices4vaadin/auth/AcmeUser.java: -------------------------------------------------------------------------------- 1 | package microservices4vaadin.auth; 2 | 3 | import java.io.Serializable; 4 | import java.time.LocalDateTime; 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | import javax.persistence.Column; 9 | import javax.persistence.Entity; 10 | import javax.persistence.FetchType; 11 | import javax.persistence.GeneratedValue; 12 | import javax.persistence.GenerationType; 13 | import javax.persistence.Id; 14 | import javax.persistence.JoinColumn; 15 | import javax.persistence.JoinTable; 16 | import javax.persistence.ManyToMany; 17 | import javax.validation.constraints.NotNull; 18 | import javax.validation.constraints.Size; 19 | 20 | import org.hibernate.annotations.Type; 21 | import org.hibernate.validator.constraints.Email; 22 | import org.springframework.format.annotation.DateTimeFormat; 23 | 24 | import com.fasterxml.jackson.annotation.JsonIgnore; 25 | 26 | import lombok.Data; 27 | 28 | 29 | /** 30 | * Entity representing a user 31 | */ 32 | @Entity 33 | @Data 34 | public class AcmeUser implements Serializable { 35 | 36 | private static final long serialVersionUID = 5862624106931867852L; 37 | 38 | public AcmeUser() {} 39 | 40 | public AcmeUser(AcmeUser acmeUser) { 41 | super(); 42 | this.itemId = acmeUser.itemId; 43 | this.email = acmeUser.email; 44 | this.password = acmeUser.password; 45 | this.activated = acmeUser.activated; 46 | this.activationKey = acmeUser.activationKey; 47 | this.authorities = acmeUser.authorities; 48 | } 49 | 50 | @Id 51 | @GeneratedValue(strategy = GenerationType.AUTO) 52 | @Column(name = "id") 53 | private long itemId; 54 | 55 | @Email 56 | @NotNull 57 | @Size(min = 0, max = 100) 58 | @Column(length = 100, unique = true) 59 | private String email; 60 | 61 | @JsonIgnore 62 | @Size(min = 0, max = 100) 63 | @Column(length = 100) 64 | private String password; 65 | 66 | boolean activated = false; 67 | 68 | @Size(min = 0, max = 20) 69 | @Column(name = "activation_key", length = 20) 70 | @JsonIgnore 71 | private String activationKey; 72 | 73 | @ManyToMany(fetch = FetchType.EAGER) 74 | @JoinTable(name = "user_2_authority", 75 | joinColumns = @JoinColumn(name = "user_id", referencedColumnName = "id"), 76 | inverseJoinColumns = @JoinColumn(name = "authority_id", referencedColumnName = "id")) 77 | private List authorities = new ArrayList(); 78 | 79 | @NotNull 80 | @Column(nullable = false, length = 50, updatable = false) 81 | private String createdBy; 82 | 83 | @NotNull 84 | @Column(nullable = false) 85 | @Type(type = "org.jadira.usertype.dateandtime.threeten.PersistentLocalDateTime") 86 | @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") 87 | private LocalDateTime createdDateTime; 88 | 89 | } 90 | -------------------------------------------------------------------------------- /microservices/authserver/src/main/java/microservices4vaadin/auth/AcmeUserDetails.java: -------------------------------------------------------------------------------- 1 | package microservices4vaadin.auth; 2 | 3 | import lombok.Data; 4 | import lombok.EqualsAndHashCode; 5 | 6 | import org.springframework.security.core.userdetails.UserDetails; 7 | 8 | /** 9 | * User Details implementation for an AcmeUser 10 | */ 11 | @Data 12 | @EqualsAndHashCode(callSuper=true) 13 | public class AcmeUserDetails extends AcmeUser implements UserDetails { 14 | 15 | private static final long serialVersionUID = -2841246955880250736L; 16 | 17 | public AcmeUserDetails(){ 18 | 19 | } 20 | 21 | public AcmeUserDetails(AcmeUser acmeUser) { 22 | super(acmeUser); 23 | } 24 | 25 | @Override 26 | public String getUsername() { 27 | return getEmail(); 28 | } 29 | 30 | @Override 31 | public boolean isAccountNonExpired() { 32 | return true; 33 | } 34 | 35 | @Override 36 | public boolean isAccountNonLocked() { 37 | return true; 38 | } 39 | 40 | @Override 41 | public boolean isCredentialsNonExpired() { 42 | return true; 43 | } 44 | 45 | @Override 46 | public boolean isEnabled() { 47 | return isActivated(); 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /microservices/authserver/src/main/java/microservices4vaadin/auth/Authorities.java: -------------------------------------------------------------------------------- 1 | package microservices4vaadin.auth; 2 | 3 | /** 4 | * Constants for Spring Security authorities. 5 | */ 6 | public final class Authorities { 7 | 8 | private Authorities() { 9 | } 10 | 11 | public static final String ADMIN = "ROLE_ADMIN"; 12 | 13 | public static final String USER = "ROLE_USER"; 14 | 15 | public static final String ANONYMOUS = "ROLE_ANONYMOUS"; 16 | } 17 | -------------------------------------------------------------------------------- /microservices/authserver/src/main/java/microservices4vaadin/auth/Authority.java: -------------------------------------------------------------------------------- 1 | package microservices4vaadin.auth; 2 | 3 | import java.io.Serializable; 4 | 5 | import javax.persistence.Column; 6 | import javax.persistence.Entity; 7 | import javax.persistence.GeneratedValue; 8 | import javax.persistence.GenerationType; 9 | import javax.persistence.Id; 10 | import javax.validation.constraints.NotNull; 11 | import javax.validation.constraints.Size; 12 | 13 | import lombok.Data; 14 | 15 | import org.springframework.security.core.GrantedAuthority; 16 | import org.springframework.security.core.authority.SimpleGrantedAuthority; 17 | 18 | 19 | /** 20 | * Defines the granted authorities currently held by an AcmeUser 21 | */ 22 | @Entity 23 | @Data 24 | public class Authority implements GrantedAuthority, Serializable { 25 | 26 | private static final long serialVersionUID = -3022031591212475416L; 27 | 28 | @Id 29 | @GeneratedValue(strategy = GenerationType.AUTO) 30 | @Column(name = "id") 31 | private long itemId; 32 | 33 | @NotNull 34 | @Size(min = 0, max = 50) 35 | @Column(length = 50) 36 | private String name; 37 | 38 | @Override 39 | public String getAuthority() { 40 | return new SimpleGrantedAuthority(name).getAuthority(); 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /microservices/authserver/src/main/java/microservices4vaadin/authserver/AuthserverApplication.java: -------------------------------------------------------------------------------- 1 | package microservices4vaadin.authserver; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.boot.autoconfigure.domain.EntityScan; 6 | import org.springframework.cloud.client.discovery.EnableDiscoveryClient; 7 | import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer; 8 | import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer; 9 | 10 | @SpringBootApplication 11 | @EntityScan(basePackages ={ "microservices4vaadin.auth" }) 12 | @EnableDiscoveryClient 13 | @EnableResourceServer 14 | @EnableAuthorizationServer 15 | public class AuthserverApplication { 16 | 17 | public static void main(String[] args) { 18 | SpringApplication.run(AuthserverApplication.class, args); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /microservices/authserver/src/main/java/microservices4vaadin/authserver/configuration/CustomAuthenticationSuccessHandler.java: -------------------------------------------------------------------------------- 1 | package microservices4vaadin.authserver.configuration; 2 | 3 | import java.io.IOException; 4 | 5 | import javax.servlet.ServletException; 6 | import javax.servlet.http.HttpServletRequest; 7 | import javax.servlet.http.HttpServletResponse; 8 | 9 | import org.springframework.security.core.Authentication; 10 | import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler; 11 | import org.springframework.stereotype.Component; 12 | 13 | @Component 14 | public class CustomAuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler { 15 | 16 | @Override 17 | public void onAuthenticationSuccess(HttpServletRequest request, 18 | HttpServletResponse response, Authentication authentication) 19 | throws IOException, ServletException { 20 | String referrer = request.getHeader("referer"); 21 | if (referrer != null) 22 | response.sendRedirect(referrer + "/index.html"); 23 | } 24 | 25 | } -------------------------------------------------------------------------------- /microservices/authserver/src/main/java/microservices4vaadin/authserver/configuration/RestClientConfiguration.java: -------------------------------------------------------------------------------- 1 | package microservices4vaadin.authserver.configuration; 2 | 3 | import org.apache.http.client.HttpClient; 4 | import org.apache.http.impl.client.HttpClients; 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.context.annotation.Configuration; 7 | import org.springframework.hateoas.hal.Jackson2HalModule; 8 | import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; 9 | import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; 10 | import org.springframework.web.client.RestTemplate; 11 | 12 | import com.fasterxml.jackson.databind.DeserializationFeature; 13 | import com.fasterxml.jackson.databind.ObjectMapper; 14 | import com.fasterxml.jackson.databind.SerializationFeature; 15 | 16 | @Configuration 17 | public class RestClientConfiguration { 18 | 19 | @Bean 20 | public RestTemplate restTemplate() { 21 | RestTemplate restTemplate = new RestTemplate(); 22 | HttpClient httpClient = HttpClients.createDefault(); 23 | restTemplate.setRequestFactory(new HttpComponentsClientHttpRequestFactory(httpClient)); 24 | 25 | ObjectMapper objectMapper = new ObjectMapper(); 26 | objectMapper.registerModule(new Jackson2HalModule()); 27 | objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); 28 | objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); 29 | objectMapper.configure(DeserializationFeature.FAIL_ON_IGNORED_PROPERTIES, false); 30 | MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(); 31 | converter.setObjectMapper(objectMapper); 32 | restTemplate.getMessageConverters().add(0, converter); 33 | 34 | return restTemplate; 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /microservices/authserver/src/main/java/microservices4vaadin/authserver/configuration/SessionConfiguration.java: -------------------------------------------------------------------------------- 1 | package microservices4vaadin.authserver.configuration; 2 | 3 | import org.springframework.beans.factory.BeanFactory; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.beans.factory.support.DefaultListableBeanFactory; 6 | import org.springframework.context.ApplicationContext; 7 | import org.springframework.context.annotation.Bean; 8 | import org.springframework.context.annotation.Configuration; 9 | import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession; 10 | import org.springframework.session.web.http.CookieHttpSessionStrategy; 11 | import org.springframework.session.web.http.DefaultCookieSerializer; 12 | import org.springframework.session.web.http.HttpSessionStrategy; 13 | 14 | @Configuration 15 | @EnableRedisHttpSession 16 | public class SessionConfiguration { 17 | 18 | private final static String SESSION_SERIALIZATION_ID = "microservices4vaadin"; 19 | 20 | @Autowired 21 | private ApplicationContext appContext; 22 | 23 | @Bean 24 | public String overwriteSerializationId() { 25 | BeanFactory beanFactory = appContext.getAutowireCapableBeanFactory(); 26 | ((DefaultListableBeanFactory) beanFactory).setSerializationId(SESSION_SERIALIZATION_ID); 27 | return "overwritten"; 28 | } 29 | 30 | @Bean 31 | public HttpSessionStrategy httpSessionStrategy() { 32 | CookieHttpSessionStrategy cookieHttpSessionStrategy = new CookieHttpSessionStrategy(); 33 | DefaultCookieSerializer cookieSerializer = new DefaultCookieSerializer(); 34 | cookieSerializer.setCookieName("JSESSIONID"); 35 | cookieSerializer.setCookiePath("/"); 36 | cookieSerializer.setDomainNamePattern("^.+?\\.(\\w+\\.[a-z]+)$"); 37 | cookieHttpSessionStrategy.setCookieSerializer(cookieSerializer); 38 | return cookieHttpSessionStrategy; 39 | } 40 | 41 | @Bean 42 | public SessionSerializer springSessionDefaultRedisSerializer() { 43 | return new SessionSerializer(); 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /microservices/authserver/src/main/java/microservices4vaadin/authserver/configuration/SessionSerializer.java: -------------------------------------------------------------------------------- 1 | package microservices4vaadin.authserver.configuration; 2 | 3 | import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer; 4 | import org.springframework.data.redis.serializer.SerializationException; 5 | 6 | //@Slf4j 7 | public class SessionSerializer extends JdkSerializationRedisSerializer { 8 | 9 | @Override 10 | public Object deserialize(byte[] bytes) { 11 | try { 12 | Object obj = super.deserialize(bytes); 13 | return obj; 14 | } 15 | catch (SerializationException se) { 16 | // whenever inexistent classes from other service are deserialized they end up here 17 | //log.debug("Ignore: ", se.getRootCause()); 18 | } 19 | 20 | return null; 21 | } 22 | 23 | @Override 24 | public byte[] serialize(Object object) { 25 | return super.serialize(object); 26 | } 27 | 28 | } -------------------------------------------------------------------------------- /microservices/authserver/src/main/java/microservices4vaadin/authserver/configuration/WebSecurityConfiguration.java: -------------------------------------------------------------------------------- 1 | package microservices4vaadin.authserver.configuration; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.context.annotation.Bean; 5 | import org.springframework.context.annotation.Configuration; 6 | import org.springframework.core.Ordered; 7 | import org.springframework.core.annotation.Order; 8 | import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; 9 | import org.springframework.security.config.annotation.web.builders.HttpSecurity; 10 | import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; 11 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; 12 | import org.springframework.security.web.authentication.AuthenticationSuccessHandler; 13 | 14 | import microservices4vaadin.authserver.service.AcmeUserDetailsService; 15 | 16 | /** 17 | * Defines the Spring Security authentication, required for authenticating users 18 | */ 19 | @Configuration 20 | @EnableWebSecurity 21 | @Order(Ordered.HIGHEST_PRECEDENCE) 22 | public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter { 23 | 24 | @Autowired 25 | private AcmeUserDetailsService userDetailsService; 26 | 27 | @Autowired 28 | void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { 29 | auth 30 | .userDetailsService(userDetailsService) 31 | .passwordEncoder(userDetailsService.getPasswordEncoder()); 32 | auth.parentAuthenticationManager(this.authenticationManager()); 33 | } 34 | 35 | @Bean 36 | public AuthenticationSuccessHandler successHandler() { 37 | return new CustomAuthenticationSuccessHandler(); 38 | } 39 | 40 | @Override 41 | protected void configure(HttpSecurity http) throws Exception { 42 | http 43 | .formLogin().loginPage("/login").successHandler(successHandler()).permitAll() 44 | .and() 45 | .requestMatchers().antMatchers("/user", "/login", "/logout", "/oauth/authorize", "/oauth_confirm_access", "/register", "/activate/**") 46 | .and() 47 | .authorizeRequests().antMatchers("/register", "/activate/**").permitAll() 48 | .and() 49 | .authorizeRequests().anyRequest().authenticated().and().csrf().disable(); 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /microservices/authserver/src/main/java/microservices4vaadin/authserver/controller/CredentialUpdateResource.java: -------------------------------------------------------------------------------- 1 | package microservices4vaadin.authserver.controller; 2 | 3 | import com.fasterxml.jackson.annotation.JsonInclude; 4 | import com.fasterxml.jackson.annotation.JsonInclude.Include; 5 | 6 | import lombok.Getter; 7 | import lombok.Setter; 8 | 9 | @Getter 10 | @Setter 11 | public class CredentialUpdateResource { 12 | 13 | @JsonInclude(Include.NON_NULL) 14 | private String email; 15 | 16 | @JsonInclude(Include.NON_NULL) 17 | private String newPassword; 18 | 19 | @JsonInclude(Include.NON_NULL) 20 | private String oldPassword; 21 | 22 | } 23 | -------------------------------------------------------------------------------- /microservices/authserver/src/main/java/microservices4vaadin/authserver/controller/UserController.java: -------------------------------------------------------------------------------- 1 | package microservices4vaadin.authserver.controller; 2 | 3 | import java.security.Principal; 4 | 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; 7 | import org.springframework.web.bind.annotation.RequestBody; 8 | import org.springframework.web.bind.annotation.RequestMapping; 9 | import org.springframework.web.bind.annotation.RequestMethod; 10 | import org.springframework.web.bind.annotation.RestController; 11 | 12 | import microservices4vaadin.auth.AcmeUserDetails; 13 | import microservices4vaadin.authserver.service.AcmeUserDetailsService; 14 | 15 | /** 16 | * Return information about the currently logged in user 17 | */ 18 | @RestController 19 | class UserController { 20 | 21 | @Autowired 22 | private AcmeUserDetailsService acmeUserDetailsService; 23 | 24 | @RequestMapping(value = "/user", method = RequestMethod.GET) 25 | public AcmeUserDetails user(Principal principal) { 26 | if(principal instanceof AcmeUserDetails) { 27 | return (AcmeUserDetails)principal; 28 | } 29 | else if(principal instanceof UsernamePasswordAuthenticationToken) { 30 | return (AcmeUserDetails)acmeUserDetailsService.loadUserByUsername(principal.getName()); 31 | } 32 | return null; 33 | } 34 | 35 | @RequestMapping(value = "/user", method = RequestMethod.PATCH) 36 | public AcmeUserDetails updateUserCredentials(Principal principal, @RequestBody CredentialUpdateResource credentials) { 37 | return (AcmeUserDetails)acmeUserDetailsService.updateUserCredentials(principal.getName(), credentials.getEmail() 38 | , credentials.getNewPassword(), credentials.getOldPassword()); 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /microservices/authserver/src/main/java/microservices4vaadin/authserver/exception/UserNotActivatedException.java: -------------------------------------------------------------------------------- 1 | package microservices4vaadin.authserver.exception; 2 | 3 | import org.springframework.security.core.AuthenticationException; 4 | 5 | /** 6 | * Thrown when the user attempting to authenticate is not activated 7 | */ 8 | public class UserNotActivatedException extends AuthenticationException{ 9 | 10 | private static final long serialVersionUID = 7485453242456652318L; 11 | 12 | public UserNotActivatedException(String msg) { 13 | super(msg); 14 | // TODO Auto-generated constructor stub 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /microservices/authserver/src/main/java/microservices4vaadin/authserver/exception/UserNotFoundException.java: -------------------------------------------------------------------------------- 1 | package microservices4vaadin.authserver.exception; 2 | 3 | import org.springframework.security.core.AuthenticationException; 4 | 5 | /** 6 | * Thrown when the provided username is not found 7 | */ 8 | public class UserNotFoundException extends AuthenticationException { 9 | 10 | private static final long serialVersionUID = 6587656019426094542L; 11 | 12 | public UserNotFoundException(String msg) { 13 | super(msg); 14 | // TODO Auto-generated constructor stub 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /microservices/authserver/src/main/java/microservices4vaadin/authserver/exception/WrongOldPasswordException.java: -------------------------------------------------------------------------------- 1 | package microservices4vaadin.authserver.exception; 2 | 3 | import org.springframework.security.core.AuthenticationException; 4 | 5 | /** 6 | * Thrown when the user attempting to authenticate is not activated 7 | */ 8 | public class WrongOldPasswordException extends AuthenticationException{ 9 | 10 | private static final long serialVersionUID = 7048741709917583284L; 11 | 12 | public WrongOldPasswordException(String msg) { 13 | super(msg); 14 | // TODO Auto-generated constructor stub 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /microservices/authserver/src/main/java/microservices4vaadin/authserver/repository/AuthorityRepository.java: -------------------------------------------------------------------------------- 1 | package microservices4vaadin.authserver.repository; 2 | 3 | import org.springframework.data.jpa.repository.JpaRepository; 4 | import org.springframework.data.repository.query.Param; 5 | import org.springframework.stereotype.Repository; 6 | 7 | import microservices4vaadin.auth.Authority; 8 | 9 | /** 10 | * A Spring data JPA repository for looking up granted authorities from the database 11 | */ 12 | @Repository 13 | public interface AuthorityRepository extends JpaRepository { 14 | 15 | Authority findOneByName(@Param("name") String name); 16 | 17 | } -------------------------------------------------------------------------------- /microservices/authserver/src/main/java/microservices4vaadin/authserver/repository/UserRepository.java: -------------------------------------------------------------------------------- 1 | package microservices4vaadin.authserver.repository; 2 | 3 | import java.time.LocalDateTime; 4 | import java.util.List; 5 | 6 | import org.springframework.data.jpa.repository.JpaRepository; 7 | import org.springframework.data.jpa.repository.Query; 8 | import org.springframework.format.annotation.DateTimeFormat; 9 | import org.springframework.format.annotation.DateTimeFormat.ISO; 10 | import org.springframework.stereotype.Repository; 11 | 12 | import microservices4vaadin.auth.AcmeUser; 13 | 14 | /** 15 | * AcmeUser Repository 16 | */ 17 | @Repository 18 | public interface UserRepository extends JpaRepository { 19 | 20 | @Query("select u from AcmeUser u where u.activationKey = ?1") 21 | AcmeUser getUserByActivationKey(String activationKey); 22 | 23 | @Query("select u from AcmeUser u where u.activated = false and u.createdDateTime > ?1") 24 | List findNotActivatedUsersByCreatedDateTimeBefore(@DateTimeFormat(iso=ISO.DATE) LocalDateTime dateTime); 25 | 26 | AcmeUser findOneByEmail(String email); 27 | 28 | } 29 | -------------------------------------------------------------------------------- /microservices/authserver/src/main/java/microservices4vaadin/authserver/rest/controller/UserEventController.java: -------------------------------------------------------------------------------- 1 | package microservices4vaadin.authserver.rest.controller; 2 | 3 | import java.net.URI; 4 | 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.core.ParameterizedTypeReference; 7 | import org.springframework.http.MediaType; 8 | import org.springframework.http.RequestEntity; 9 | import org.springframework.http.ResponseEntity; 10 | import org.springframework.stereotype.Controller; 11 | import org.springframework.web.client.RestOperations; 12 | 13 | import lombok.extern.slf4j.Slf4j; 14 | import microservices4vaadin.authserver.rest.controller.util.RestUtils; 15 | import microservices4vaadin.authserver.service.Registration; 16 | import microservices4vaadin.userevents.UserCreatedEvent; 17 | 18 | @Controller 19 | @Slf4j 20 | public class UserEventController { 21 | 22 | public final static String USER_EVENT_REST_URL = "/user"; 23 | 24 | @Autowired 25 | private RestOperations restTemplate; 26 | 27 | @Autowired 28 | private RestUtils restUtils; 29 | 30 | public void publishCreatedUserEvent(Long id, Registration registration) { 31 | log.debug("Setting up REST call to publish an CreatedUserEvent"); 32 | 33 | UserCreatedEvent userCreatedEvent = new UserCreatedEvent(); 34 | userCreatedEvent.setId(id); 35 | userCreatedEvent.setEmail(registration.getEmail()); 36 | userCreatedEvent.setFirstName(registration.getFirstName()); 37 | userCreatedEvent.setLastName(registration.getLastName()); 38 | 39 | RequestEntity request = RequestEntity.post(URI.create(restUtils.getServiceUrl("eventstore") + USER_EVENT_REST_URL + "/createdEvent")) 40 | //.accept(MediaTypes.HAL_JSON) 41 | .contentType(MediaType.APPLICATION_JSON).body(userCreatedEvent); 42 | ResponseEntity resourceEntity = restTemplate.exchange(request, new ParameterizedTypeReference() {}); 43 | log.debug("REST call returned: {}", resourceEntity.getBody()); 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /microservices/authserver/src/main/java/microservices4vaadin/authserver/rest/controller/util/RestUtils.java: -------------------------------------------------------------------------------- 1 | package microservices4vaadin.authserver.rest.controller.util; 2 | 3 | import java.net.URI; 4 | 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.cloud.client.ServiceInstance; 7 | import org.springframework.cloud.client.loadbalancer.LoadBalancerClient; 8 | import org.springframework.http.HttpStatus; 9 | import org.springframework.http.ResponseEntity; 10 | import org.springframework.stereotype.Component; 11 | 12 | import lombok.extern.slf4j.Slf4j; 13 | 14 | @Component 15 | @Slf4j 16 | public class RestUtils { 17 | 18 | public static final String PROJECTION_PARAMETER_NAME = "projection"; 19 | public static final String PROJECTION_PARAMETER_VALUE_BASE = "base"; 20 | 21 | @Autowired 22 | private LoadBalancerClient loadBalancer; 23 | 24 | /** 25 | * 26 | * @param serviceId 27 | * @return 28 | */ 29 | public URI getServiceUrl(String serviceId) { 30 | return getServiceUrl(serviceId, null); 31 | } 32 | 33 | /** 34 | * 35 | * @param serviceId 36 | * @param fallbackUri 37 | * @return 38 | */ 39 | protected URI getServiceUrl(String serviceId, String fallbackUri) { 40 | URI uri = null; 41 | try { 42 | ServiceInstance instance = loadBalancer.choose(serviceId); 43 | 44 | if (instance == null) { 45 | throw new RuntimeException("Can't find a service with serviceId = " + serviceId); 46 | } 47 | 48 | uri = instance.getUri(); 49 | log.debug("Resolved serviceId '{}' to URL '{}'.", serviceId, uri); 50 | 51 | } catch (RuntimeException e) { 52 | // Eureka not available, use fallback if specified otherwise rethrow the error 53 | if (fallbackUri == null) { 54 | throw e; 55 | 56 | } else { 57 | uri = URI.create(fallbackUri); 58 | log.warn("Failed to resolve serviceId '{}'. Fallback to URL '{}'.", serviceId, uri); 59 | } 60 | } 61 | 62 | return uri; 63 | } 64 | 65 | public ResponseEntity createOkResponse(T body) { 66 | return createResponse(body, HttpStatus.OK); 67 | } 68 | 69 | public ResponseEntity createResponse(T body, HttpStatus httpStatus) { 70 | return new ResponseEntity<>(body, httpStatus); 71 | } 72 | 73 | } -------------------------------------------------------------------------------- /microservices/authserver/src/main/java/microservices4vaadin/authserver/service/AcmeUserDetailsService.java: -------------------------------------------------------------------------------- 1 | package microservices4vaadin.authserver.service; 2 | 3 | import lombok.Getter; 4 | import lombok.extern.slf4j.Slf4j; 5 | import microservices4vaadin.auth.AcmeUser; 6 | import microservices4vaadin.auth.AcmeUserDetails; 7 | import microservices4vaadin.authserver.exception.UserNotActivatedException; 8 | import microservices4vaadin.authserver.exception.UserNotFoundException; 9 | import microservices4vaadin.authserver.exception.WrongOldPasswordException; 10 | import microservices4vaadin.authserver.repository.UserRepository; 11 | 12 | import javax.servlet.http.HttpSession; 13 | 14 | import org.springframework.beans.factory.annotation.Autowired; 15 | import org.springframework.security.core.userdetails.UserDetails; 16 | import org.springframework.security.core.userdetails.UserDetailsService; 17 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 18 | import org.springframework.security.crypto.password.PasswordEncoder; 19 | import org.springframework.stereotype.Component; 20 | import org.springframework.transaction.annotation.Transactional; 21 | 22 | /** 23 | * Loads user specific AcmeUser data 24 | */ 25 | @Component("userDetailsService") 26 | @Slf4j 27 | public class AcmeUserDetailsService implements UserDetailsService { 28 | 29 | private static final String SESSION_USER_ATTRIBUTE_NAME="user"; 30 | 31 | @Autowired 32 | private UserRepository userRepository; 33 | 34 | @Autowired 35 | private HttpSession httpSession; 36 | 37 | @Getter 38 | private PasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); 39 | 40 | @Override 41 | @Transactional 42 | public UserDetails loadUserByUsername(final String email) { 43 | log.debug("Authenticating {}", email); 44 | AcmeUser acmeUser = findUserByEmail(email.toLowerCase()); 45 | AcmeUserDetails acmeUserDetails = new AcmeUserDetails(acmeUser); 46 | httpSession.setAttribute(SESSION_USER_ATTRIBUTE_NAME, acmeUserDetails); 47 | return acmeUserDetails; 48 | } 49 | 50 | private AcmeUser findUserByEmail(String lowercaseEmail) { 51 | AcmeUser acmeUser = userRepository.findOneByEmail(lowercaseEmail); 52 | if (acmeUser == null) { 53 | throw new UserNotFoundException("User " + lowercaseEmail + " was not found in the database"); 54 | } else if (!acmeUser.isActivated()) { 55 | throw new UserNotActivatedException("User " + lowercaseEmail + " was not activated"); 56 | } 57 | return acmeUser; 58 | } 59 | 60 | @Transactional 61 | public UserDetails updateUserCredentials(String oldEmail, String email, String newPassword, String oldPassword) { 62 | AcmeUser acmeUser = findUserByEmail(oldEmail.toLowerCase()); // this would fail if email is wrong 63 | if (newPassword != null && !newPassword.equals("")) { 64 | if (!passwordEncoder.matches(oldPassword, acmeUser.getPassword())) 65 | throw new WrongOldPasswordException("Wrong old password for user " + email); 66 | acmeUser.setPassword(passwordEncoder.encode(newPassword)); 67 | } 68 | if (email != null && !email.equals("")) 69 | acmeUser.setEmail(email); 70 | userRepository.save(acmeUser); 71 | AcmeUserDetails acmeUserDetails = new AcmeUserDetails(acmeUser); 72 | httpSession.setAttribute(SESSION_USER_ATTRIBUTE_NAME, acmeUserDetails); 73 | return acmeUserDetails; 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /microservices/authserver/src/main/java/microservices4vaadin/authserver/service/ActivationService.java: -------------------------------------------------------------------------------- 1 | package microservices4vaadin.authserver.service; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.scheduling.annotation.Scheduled; 7 | import org.springframework.stereotype.Service; 8 | 9 | import microservices4vaadin.auth.AcmeUser; 10 | import microservices4vaadin.authserver.repository.UserRepository; 11 | 12 | import java.time.LocalDateTime; 13 | import java.util.List; 14 | import java.util.Optional; 15 | 16 | /** 17 | * Handles registering and activating users. Also cleans up users who have not activated 18 | * in a reasonable amount of time 19 | */ 20 | @Service 21 | public class ActivationService { 22 | 23 | private final Logger log = LoggerFactory.getLogger(ActivationService.class); 24 | 25 | @Autowired 26 | private UserRepository userRepository; 27 | 28 | 29 | /** 30 | * Activates the user with the given registration key 31 | * @param key - the activation key 32 | * @return The activated user 33 | */ 34 | public AcmeUser activateUser(String key) { 35 | return Optional.ofNullable(userRepository.getUserByActivationKey(key)) 36 | .map(user -> { 37 | user.setActivated(true); 38 | user.setActivationKey(null); 39 | userRepository.save(user); 40 | log.debug("Activated user: {}", user); 41 | return user; 42 | }) 43 | .orElse(null); 44 | } 45 | 46 | /** 47 | * Non-activated users should be automatically deleted after 3 days. 48 | *

49 | *

50 | * This is scheduled to get fired everyday, at 01:00 (am). 51 | *

52 | */ 53 | @Scheduled(cron = "0 0 1 * * ?") 54 | public void removeNonActivatedUsers() { 55 | LocalDateTime now = LocalDateTime.now(); 56 | List users = userRepository.findNotActivatedUsersByCreatedDateTimeBefore(now.minusDays(3)); 57 | for (AcmeUser user : users) { 58 | log.debug("Deleting not activated user {}", user.getEmail()); 59 | userRepository.delete(user); 60 | } 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /microservices/authserver/src/main/java/microservices4vaadin/authserver/service/EmailService.java: -------------------------------------------------------------------------------- 1 | package microservices4vaadin.authserver.service; 2 | 3 | import org.springframework.mail.javamail.JavaMailSender; 4 | 5 | public interface EmailService { 6 | 7 | JavaMailSender getMailSender(); 8 | 9 | } 10 | -------------------------------------------------------------------------------- /microservices/authserver/src/main/java/microservices4vaadin/authserver/service/EmailServiceImpl.java: -------------------------------------------------------------------------------- 1 | package microservices4vaadin.authserver.service; 2 | 3 | import java.util.Properties; 4 | 5 | 6 | import org.springframework.beans.factory.annotation.Value; 7 | import org.springframework.mail.javamail.JavaMailSender; 8 | import org.springframework.mail.javamail.JavaMailSenderImpl; 9 | import org.springframework.stereotype.Repository; 10 | import org.springframework.stereotype.Service; 11 | import org.springframework.transaction.annotation.Transactional; 12 | 13 | @Repository 14 | @Transactional 15 | @Service("emailService") 16 | public class EmailServiceImpl implements EmailService { 17 | 18 | private @Value("${mail.smtp.host}") String emailHost; 19 | private @Value("${mail.smtp.port}") int emailPort; 20 | private @Value("${email.username}") String userName; 21 | private @Value("${email.password}") String password; 22 | private @Value("${mail.smtp.auth}") String mailAuth; 23 | 24 | @Override 25 | public JavaMailSender getMailSender() { 26 | JavaMailSenderImpl ms = new JavaMailSenderImpl(); 27 | ms.setHost(emailHost); 28 | ms.setPort(emailPort); 29 | ms.setUsername(userName); 30 | ms.setPassword(password); 31 | Properties pp = new Properties(); 32 | pp.setProperty("mail.smtp.auth", mailAuth); 33 | ms.setJavaMailProperties(pp); 34 | return ms; 35 | } 36 | 37 | } -------------------------------------------------------------------------------- /microservices/authserver/src/main/java/microservices4vaadin/authserver/service/FreemarkerEmailService.java: -------------------------------------------------------------------------------- 1 | package microservices4vaadin.authserver.service; 2 | 3 | import java.io.IOException; 4 | import java.util.Map; 5 | 6 | import freemarker.template.TemplateException; 7 | 8 | public interface FreemarkerEmailService { 9 | 10 | void sendMail(String templateName, Map emailModel, 11 | Map model) throws IOException, TemplateException; 12 | 13 | } 14 | -------------------------------------------------------------------------------- /microservices/authserver/src/main/java/microservices4vaadin/authserver/service/FreemarkerEmailServiceImpl.java: -------------------------------------------------------------------------------- 1 | package microservices4vaadin.authserver.service; 2 | 3 | import java.io.IOException; 4 | import java.util.Map; 5 | 6 | import javax.mail.internet.MimeMessage; 7 | 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.mail.javamail.MimeMessageHelper; 10 | import org.springframework.mail.javamail.MimeMessagePreparator; 11 | import org.springframework.stereotype.Repository; 12 | import org.springframework.stereotype.Service; 13 | import org.springframework.transaction.annotation.Transactional; 14 | import org.springframework.ui.freemarker.FreeMarkerTemplateUtils; 15 | import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer; 16 | 17 | import freemarker.template.Template; 18 | import freemarker.template.TemplateException; 19 | import microservices4vaadin.authserver.util.ConstantsUtil; 20 | 21 | @Repository 22 | @Transactional 23 | @Service("freemarkerEmailService") 24 | public class FreemarkerEmailServiceImpl implements FreemarkerEmailService { 25 | 26 | @Autowired 27 | private EmailService emailService; 28 | 29 | @Autowired 30 | private FreeMarkerConfigurer freeMarkerConfigurer; 31 | 32 | @Override 33 | public void sendMail(String templateName, final Map emailModel, Map model) throws IOException, TemplateException { 34 | 35 | Template t = freeMarkerConfigurer.getConfiguration().getTemplate(templateName); 36 | model.put("ctx", ConstantsUtil.SITEURL); 37 | final String text = FreeMarkerTemplateUtils.processTemplateIntoString(t, model); 38 | 39 | MimeMessagePreparator preparator = new MimeMessagePreparator() { 40 | @Override 41 | public void prepare(MimeMessage mimeMessage) throws Exception { 42 | MimeMessageHelper message = new MimeMessageHelper(mimeMessage,true,"GBK"); 43 | message.setTo(emailModel.get(ConstantsUtil.MAIL_RECEIVE)); 44 | message.setSubject(emailModel.get(ConstantsUtil.MAIL_SUBJECT)); 45 | message.setFrom(emailModel.get(ConstantsUtil.MAIL_SEND)); 46 | message.setText(text, true); 47 | } 48 | }; 49 | emailService.getMailSender().send(preparator); 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /microservices/authserver/src/main/java/microservices4vaadin/authserver/service/Registration.java: -------------------------------------------------------------------------------- 1 | package microservices4vaadin.authserver.service; 2 | 3 | import lombok.Data; 4 | 5 | @Data 6 | public class Registration { 7 | 8 | private String password; 9 | private String firstName; 10 | private String lastName; 11 | private String email; 12 | 13 | } 14 | -------------------------------------------------------------------------------- /microservices/authserver/src/main/java/microservices4vaadin/authserver/service/RegistrationService.java: -------------------------------------------------------------------------------- 1 | package microservices4vaadin.authserver.service; 2 | 3 | import microservices4vaadin.auth.AcmeUser; 4 | 5 | 6 | public interface RegistrationService { 7 | 8 | /** 9 | * Registers a new user 10 | * 11 | * @param email - the email for the new user 12 | * @param password - the password for the new user 13 | * @param firstName - the new users first name 14 | * @param lastName - the new users last name 15 | * @return the activation code 16 | */ 17 | AcmeUser registerUser(Registration registration); 18 | 19 | } -------------------------------------------------------------------------------- /microservices/authserver/src/main/java/microservices4vaadin/authserver/service/RegistrationServiceImpl.java: -------------------------------------------------------------------------------- 1 | package microservices4vaadin.authserver.service; 2 | 3 | import java.time.LocalDateTime; 4 | import java.util.ArrayList; 5 | import java.util.List; 6 | 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.stereotype.Service; 9 | 10 | import lombok.extern.slf4j.Slf4j; 11 | import microservices4vaadin.auth.AcmeUser; 12 | import microservices4vaadin.auth.Authorities; 13 | import microservices4vaadin.auth.Authority; 14 | import microservices4vaadin.authserver.repository.AuthorityRepository; 15 | import microservices4vaadin.authserver.repository.UserRepository; 16 | import microservices4vaadin.authserver.util.RandomUtil; 17 | 18 | /** 19 | * Register new users 20 | */ 21 | @Service 22 | @Slf4j 23 | public class RegistrationServiceImpl implements RegistrationService { 24 | 25 | @Autowired 26 | private AcmeUserDetailsService userDetailsService; 27 | 28 | @Autowired 29 | private UserRepository userRepository; 30 | 31 | @Autowired 32 | private AuthorityRepository authorityRepository; 33 | 34 | /* (non-Javadoc) 35 | * @see microservices4vaadin.service.RegistrationService#registerUser(microservices4vaadin.service.Registration) 36 | */ 37 | @Override 38 | public AcmeUser registerUser(Registration registration) { 39 | AcmeUser newUser = new AcmeUser(); 40 | //default new users to ROLE_USER 41 | Authority authority = authorityRepository.findOneByName(Authorities.USER); 42 | List authorities = new ArrayList(); 43 | String encryptedPassword = userDetailsService.getPasswordEncoder().encode(registration.getPassword()); 44 | newUser.setEmail(registration.getEmail()); 45 | newUser.setPassword(encryptedPassword); 46 | // new user is not active 47 | newUser.setActivated(false); 48 | // new user gets registration key 49 | newUser.setActivationKey(RandomUtil.generateActivationKey()); 50 | authorities.add(authority); 51 | newUser.setAuthorities(authorities); 52 | newUser.setCreatedBy("system"); 53 | newUser.setCreatedDateTime(LocalDateTime.now()); 54 | userRepository.save(newUser); 55 | log.debug("Created User: {}", newUser); 56 | return newUser; 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /microservices/authserver/src/main/java/microservices4vaadin/authserver/util/ConstantsUtil.java: -------------------------------------------------------------------------------- 1 | package microservices4vaadin.authserver.util; 2 | 3 | import lombok.Getter; 4 | 5 | @Getter 6 | public class ConstantsUtil { 7 | 8 | public static String SITEURL = "http://localhost:8080"; 9 | 10 | public static String MAIL_RECEIVE = "mail_receive" ; 11 | public static String MAIL_SUBJECT = "mail_subject" ; 12 | public static String MAIL_SEND = "mail_subject" ; 13 | 14 | } 15 | -------------------------------------------------------------------------------- /microservices/authserver/src/main/java/microservices4vaadin/authserver/util/RandomUtil.java: -------------------------------------------------------------------------------- 1 | package microservices4vaadin.authserver.util; 2 | 3 | import org.apache.commons.lang3.RandomStringUtils; 4 | 5 | import java.security.SecureRandom; 6 | 7 | /** 8 | * Utility class for generating random Strings. 9 | */ 10 | public final class RandomUtil { 11 | private static final SecureRandom SECURE_RANDOM = new SecureRandom(); 12 | 13 | private static final int DEF_COUNT = 20; 14 | 15 | static { 16 | SECURE_RANDOM.nextBytes(new byte[64]); 17 | } 18 | 19 | private RandomUtil() { 20 | } 21 | 22 | private static String generateRandomAlphanumericString() { 23 | return RandomStringUtils.random(DEF_COUNT, 0, 0, true, true, null, SECURE_RANDOM); 24 | } 25 | 26 | /** 27 | * Generates a password. 28 | * 29 | * @return the generated password 30 | */ 31 | public static String generatePassword() { 32 | return generateRandomAlphanumericString(); 33 | } 34 | 35 | /** 36 | * Generates an activation key. 37 | * 38 | * @return the generated activation key 39 | */ 40 | public static String generateActivationKey() { 41 | return generateRandomAlphanumericString(); 42 | } 43 | 44 | } -------------------------------------------------------------------------------- /microservices/authserver/src/main/java/microservices4vaadin/authserver/util/SecurityUtil.java: -------------------------------------------------------------------------------- 1 | package microservices4vaadin.authserver.util; 2 | 3 | import org.springframework.security.core.Authentication; 4 | import org.springframework.security.core.GrantedAuthority; 5 | import org.springframework.security.core.context.SecurityContext; 6 | import org.springframework.security.core.context.SecurityContextHolder; 7 | import org.springframework.security.core.userdetails.UserDetails; 8 | 9 | import microservices4vaadin.auth.Authorities; 10 | 11 | import java.util.Collection; 12 | 13 | /** 14 | * Utility class for Spring Security. 15 | */ 16 | public final class SecurityUtil { 17 | 18 | private SecurityUtil() { 19 | } 20 | 21 | /** 22 | * Get the login of the current user. 23 | */ 24 | public static String getCurrentLogin() { 25 | SecurityContext securityContext = SecurityContextHolder.getContext(); 26 | Authentication authentication = securityContext.getAuthentication(); 27 | UserDetails springSecurityUser = null; 28 | String userName = null; 29 | 30 | if(authentication != null) { 31 | if (authentication.getPrincipal() instanceof UserDetails) { 32 | springSecurityUser = (UserDetails) authentication.getPrincipal(); 33 | userName = springSecurityUser.getUsername(); 34 | } else if (authentication.getPrincipal() instanceof String) { 35 | userName = (String) authentication.getPrincipal(); 36 | } 37 | } 38 | 39 | return userName; 40 | } 41 | 42 | /** 43 | * Check if a user is authenticated. 44 | * 45 | * @return true if the user is authenticated, false otherwise 46 | */ 47 | public static boolean isAuthenticated() { 48 | SecurityContext securityContext = SecurityContextHolder.getContext(); 49 | 50 | final Collection authorities = securityContext.getAuthentication().getAuthorities(); 51 | 52 | if (authorities != null) { 53 | for (GrantedAuthority authority : authorities) { 54 | if (authority.getAuthority().equals(Authorities.ANONYMOUS)) { 55 | return false; 56 | } 57 | } 58 | }else { 59 | return false; 60 | } 61 | 62 | return true; 63 | } 64 | 65 | } -------------------------------------------------------------------------------- /microservices/authserver/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | contextPath: /uaa 3 | port: 7777 4 | ssl: 5 | key-store: classpath:keystore.jks 6 | key-store-password: example 7 | key-password: example 8 | 9 | eureka: 10 | instance: 11 | nonSecurePortEnabled: false 12 | securePortEnabled: true 13 | securePort: 7777 14 | 15 | email: 16 | username: USERNAME 17 | password: PASSWORD 18 | mail: 19 | smtp: 20 | host: smtp.gmail.com 21 | port: 587 22 | auth: true 23 | starttls: 24 | enable: true 25 | 26 | security: 27 | sessions: stateless 28 | basic: 29 | enabled: false 30 | 31 | spring: 32 | application: 33 | name: authserver 34 | profiles: 35 | active: ${profile:default} 36 | redis: 37 | host: localhost 38 | port: 6379 39 | # DataSource settings: set here your own configurations for the database 40 | # connection. 41 | datasource: 42 | url: jdbc:mysql://localhost:3306/microservices4vaadin_authserverdb?useSSL=false&zeroDateTimeBehavior=convertToNull 43 | username: root 44 | password: 45 | driverClassName: com.mysql.jdbc.Driver 46 | testOnBorrow: true 47 | validationQuery: SELECT 1 48 | jpa: 49 | # Specify the DBMS 50 | database: MYSQL 51 | # Show or not log for each sql query 52 | show-sql: false 53 | hibernate: 54 | # Hibernate ddl auto (create, create-drop, update) 55 | ddl-auto: none 56 | # Naming strategy 57 | naming-strategy: org.hibernate.cfg.ImprovedNamingStrategy 58 | properties: 59 | hibernate: 60 | # Use spring.jpa.properties.* for Hibernate native properties (the prefix is 61 | # stripped before adding them to the entity manager) 62 | dialect: org.hibernate.dialect.MySQL5Dialect 63 | 64 | flyway: 65 | enabled: true 66 | baseline-on-migrate: true 67 | 68 | logging: 69 | level: 70 | microservices4vaadin: INFO 71 | org.springframework.session: INFO 72 | org.springframework.security: INFO 73 | com.netflix.discovery: 'OFF' 74 | 75 | --- 76 | # For deployment in Docker containers 77 | spring: 78 | profiles: docker 79 | redis: 80 | host: redis 81 | datasource: 82 | url: jdbc:mysql://mysql/microservices4vaadin_authserverdb?useSSL=false&zeroDateTimeBehavior=convertToNull 83 | 84 | eureka: 85 | client: 86 | serviceUrl: 87 | defaultZone: http://discovery:8761/eureka/ 88 | 89 | -------------------------------------------------------------------------------- /microservices/authserver/src/main/resources/bootstrap.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: authserver 4 | cloud: 5 | config: 6 | uri: http://localhost:8888 7 | 8 | --- 9 | # For deployment in Docker containers 10 | spring: 11 | profiles: docker 12 | cloud: 13 | config: 14 | uri: http://192.168.59.103:8888 15 | -------------------------------------------------------------------------------- /microservices/authserver/src/main/resources/db/migration/V000001__init.sql: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khauser/microservices4vaadin/05aab5a8ee0484004bd3368184c617c2853c86be/microservices/authserver/src/main/resources/db/migration/V000001__init.sql -------------------------------------------------------------------------------- /microservices/authserver/src/main/resources/db/migration/V000002__remove_user_details.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE `acme_user` 2 | DROP COLUMN `first_name`, 3 | DROP COLUMN `last_name`, 4 | DROP COLUMN `last_modified_by`, 5 | DROP COLUMN `last_modified_date`; 6 | 7 | ALTER TABLE `acme_user` 8 | CHANGE `created_date` `created_date_time` DATETIME AFTER `created_by`; 9 | 10 | ALTER TABLE `acme_user` MODIFY `created_date_time` DATETIME NOT NULL; 11 | -------------------------------------------------------------------------------- /microservices/authserver/src/main/resources/keystore.jks: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khauser/microservices4vaadin/05aab5a8ee0484004bd3368184c617c2853c86be/microservices/authserver/src/main/resources/keystore.jks -------------------------------------------------------------------------------- /microservices/authserver/src/test/java/microservices4vaadin/authserver/rest/BasePersistenceTest.java: -------------------------------------------------------------------------------- 1 | package microservices4vaadin.authserver.rest; 2 | 3 | import java.sql.SQLException; 4 | 5 | import javax.annotation.PostConstruct; 6 | import javax.sql.DataSource; 7 | 8 | import org.dbunit.DatabaseTestCase; 9 | import org.dbunit.DatabaseUnitException; 10 | import org.dbunit.database.DatabaseConfig; 11 | import org.dbunit.database.DatabaseConnection; 12 | import org.dbunit.database.IDatabaseConnection; 13 | import org.dbunit.dataset.IDataSet; 14 | import org.dbunit.dataset.xml.FlatXmlDataSetBuilder; 15 | import org.dbunit.ext.hsqldb.HsqldbDataTypeFactory; 16 | import org.dbunit.operation.DatabaseOperation; 17 | import org.junit.runner.RunWith; 18 | import org.springframework.beans.factory.annotation.Autowired; 19 | import org.springframework.boot.test.context.SpringBootTest; 20 | import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; 21 | import org.springframework.test.context.ActiveProfiles; 22 | import org.springframework.test.context.junit4.SpringRunner; 23 | import org.springframework.transaction.annotation.EnableTransactionManagement; 24 | 25 | @SpringBootTest(webEnvironment=WebEnvironment.RANDOM_PORT) 26 | @RunWith(SpringRunner.class) 27 | @EnableTransactionManagement 28 | @ActiveProfiles("test") 29 | public abstract class BasePersistenceTest extends DatabaseTestCase { 30 | 31 | protected static final String DATASET = "lessor_resource_test_dataset.xml"; 32 | 33 | @PostConstruct 34 | public void init() throws DatabaseUnitException, SQLException, Exception { 35 | DatabaseOperation.CLEAN_INSERT.execute(getConnection(), getDataSet()); 36 | } 37 | 38 | @Autowired 39 | private DataSource datasource; 40 | 41 | @Override 42 | protected IDatabaseConnection getConnection() throws Exception { 43 | DatabaseConnection connection = new DatabaseConnection(datasource.getConnection()); 44 | DatabaseConfig dbConfig = connection.getConfig(); 45 | dbConfig.setProperty(DatabaseConfig.PROPERTY_DATATYPE_FACTORY, new HsqldbDataTypeFactory()); 46 | return connection; 47 | } 48 | 49 | @Override 50 | protected IDataSet getDataSet() throws Exception { 51 | FlatXmlDataSetBuilder builder = new FlatXmlDataSetBuilder(); 52 | builder.setColumnSensing(true); 53 | return builder.build(this.getClass().getClassLoader().getResourceAsStream(DATASET)); 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /microservices/authserver/src/test/resources/application-test.yml: -------------------------------------------------------------------------------- 1 | server: 2 | ssl: 3 | enabled: false 4 | 5 | spring: 6 | datasource: 7 | url: jdbc:hsqldb:mem://microservices4vaadin_authservertestdb?useSSL=false 8 | username: sa 9 | password: 10 | driverClassName: org.hsqldb.jdbcDriver 11 | validationQuery: SELECT 1 FROM INFORMATION_SCHEMA.SYSTEM_USERS 12 | jpa: 13 | generate-ddl: true 14 | show-sql: false 15 | hibernate: 16 | ddl-auto: create 17 | naming-strategy: org.hibernate.cfg.ImprovedNamingStrategy 18 | properties: 19 | hibernate: 20 | dialect: org.hibernate.dialect.HSQLDialect 21 | 22 | flyway: 23 | enabled: false -------------------------------------------------------------------------------- /microservices/authserver/src/test/resources/lessor_empty_dataset.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /microservices/authserver/src/test/resources/lessor_resource_test_dataset.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /microservices/config/.gitignore: -------------------------------------------------------------------------------- 1 | .classpath 2 | .gradle/ 3 | .project 4 | .settings/ 5 | build/ 6 | /bin/ 7 | *.cache 8 | -------------------------------------------------------------------------------- /microservices/config/build.gradle: -------------------------------------------------------------------------------- 1 | jar { 2 | baseName = 'config' 3 | version = '0.0.1-SNAPSHOT' 4 | } 5 | 6 | ext { 7 | //docker 8 | imageName = dockerRepository + jar.baseName 9 | version = jar.version 10 | dockerBaseImage = 'anapsix/alpine-java:jre8' 11 | dockerExposePort = 8888 12 | } 13 | 14 | dependencies { 15 | compile('org.springframework.cloud:spring-cloud-config-server') 16 | } 17 | -------------------------------------------------------------------------------- /microservices/config/src/main/java/microservices4vaadin/configserver/ConfigServerApplication.java: -------------------------------------------------------------------------------- 1 | package microservices4vaadin.configserver; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.EnableAutoConfiguration; 5 | import org.springframework.cloud.client.discovery.EnableDiscoveryClient; 6 | import org.springframework.cloud.config.server.EnableConfigServer; 7 | import org.springframework.context.annotation.Configuration; 8 | 9 | @Configuration 10 | @EnableAutoConfiguration 11 | @EnableDiscoveryClient 12 | @EnableConfigServer 13 | public class ConfigServerApplication { 14 | 15 | public static void main(String[] args) { 16 | SpringApplication.run(ConfigServerApplication.class, args); 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /microservices/config/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 8888 3 | 4 | eureka: 5 | instance: 6 | hostname: configserver 7 | client: 8 | serviceUrl: 9 | defaultZone: http://localhost:8761/eureka/ 10 | 11 | spring: 12 | cloud: 13 | config: 14 | server: 15 | git: 16 | uri: https://github.com/khauser/microservices4vaadin-config 17 | -------------------------------------------------------------------------------- /microservices/config/src/main/resources/bootstrap.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: configserver 4 | -------------------------------------------------------------------------------- /microservices/discovery/.gitignore: -------------------------------------------------------------------------------- 1 | .classpath 2 | .gradle/ 3 | .project 4 | .settings/ 5 | build/ 6 | /bin/ 7 | *.cache 8 | -------------------------------------------------------------------------------- /microservices/discovery/build.gradle: -------------------------------------------------------------------------------- 1 | jar { 2 | baseName = 'discovery' 3 | version = '0.0.1-SNAPSHOT' 4 | } 5 | ext { 6 | //docker 7 | imageName = dockerRepository + jar.baseName 8 | version = jar.version 9 | dockerBaseImage = 'anapsix/alpine-java:jre8' 10 | dockerExposePort = 8080 11 | } 12 | 13 | dependencies { 14 | compile("org.springframework.cloud:spring-cloud-netflix-eureka-server") 15 | } 16 | -------------------------------------------------------------------------------- /microservices/discovery/docker-entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | CONTAINER_IP='http://rancher-metadata.rancher.internal/latest/self/container/primary_ip' 4 | 5 | STATUS_CODE=$(curl --write-out %{http_code} --silent --output /dev/null ${CONTAINER_IP}) 6 | 7 | if [ "$STATUS_CODE" -eq "200" ] ; then 8 | EUREKA_INSTANCE_HOSTNAME=$(curl http://rancher-metadata.rancher.internal/latest/self/container/primary_ip) 9 | echo "Instance hostname: " . $EUREKA_INSTANCE_HOSTNAME 10 | exec java -jar -Djava.security.egd=file:/dev/./urandom -Dspring.profiles.active=docker -Deureka.instance.preferIpAddress=true -Deureka.instance.ipAddress=$EUREKA_INSTANCE_HOSTNAME -Deureka.instance.hostname=$EUREKA_INSTANCE_HOSTNAME /app.jar 11 | else 12 | exec java -jar -Djava.security.egd=file:/dev/./urandom -Dspring.profiles.active=docker /app.jar 13 | fi 14 | -------------------------------------------------------------------------------- /microservices/discovery/src/main/java/microservices4vaadin/discovery/EurekaApplication.java: -------------------------------------------------------------------------------- 1 | package microservices4vaadin.discovery; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.cloud.client.discovery.EnableDiscoveryClient; 6 | import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; 7 | 8 | @SpringBootApplication 9 | @EnableEurekaServer 10 | @EnableDiscoveryClient 11 | public class EurekaApplication { 12 | 13 | public static void main(String[] args) { 14 | SpringApplication.run(EurekaApplication.class, args); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /microservices/discovery/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 8761 3 | 4 | eureka: 5 | instance: 6 | hostname: discovery 7 | client: 8 | registerWithEureka: false 9 | fetchRegistry: false 10 | serviceUrl: 11 | defaultZone: http://${eureka.host:localhost}:${eureka.port:8761}/eureka/ 12 | -------------------------------------------------------------------------------- /microservices/discovery/src/main/resources/bootstrap.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: eureka 4 | cloud: 5 | config: 6 | uri: http://localhost:8888 7 | 8 | --- 9 | # For deployment in Docker containers 10 | spring: 11 | profiles: docker 12 | cloud: 13 | config: 14 | uri: http://192.168.59.103:8888 15 | -------------------------------------------------------------------------------- /microservices/discovery/src/test/java/microservices4vaadin/discovery/ApplicationTests.java: -------------------------------------------------------------------------------- 1 | package microservices4vaadin.discovery; 2 | 3 | import static org.junit.Assert.assertEquals; 4 | 5 | import java.util.Map; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | import org.springframework.boot.context.embedded.LocalServerPort; 10 | import org.springframework.boot.test.context.SpringBootTest; 11 | import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; 12 | import org.springframework.boot.test.web.client.TestRestTemplate; 13 | import org.springframework.http.HttpStatus; 14 | import org.springframework.http.ResponseEntity; 15 | import org.springframework.test.context.junit4.SpringRunner; 16 | 17 | @SpringBootTest(webEnvironment=WebEnvironment.RANDOM_PORT) 18 | @RunWith(SpringRunner.class) 19 | public class ApplicationTests { 20 | 21 | @LocalServerPort 22 | private int port = 0; 23 | 24 | @Test 25 | public void catalogLoads() { 26 | @SuppressWarnings("rawtypes") 27 | ResponseEntity entity = new TestRestTemplate("user", "password").getForEntity("http://localhost:" + port + "/eureka/apps", Map.class); 28 | assertEquals(HttpStatus.OK, entity.getStatusCode()); 29 | } 30 | 31 | // @Test 32 | // public void adminLoads() { 33 | // @SuppressWarnings("rawtypes") 34 | // ResponseEntity entity = new TestRestTemplate("user", "password").getForEntity("http://localhost:" + port + "/env", Map.class); 35 | // assertEquals(HttpStatus.OK, entity.getStatusCode()); 36 | // } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /microservices/edge/.gitignore: -------------------------------------------------------------------------------- 1 | .classpath 2 | .gradle/ 3 | .project 4 | .settings/ 5 | build/ 6 | /bin/ 7 | *.cache 8 | -------------------------------------------------------------------------------- /microservices/edge/build.gradle: -------------------------------------------------------------------------------- 1 | jar { 2 | baseName = 'edge' 3 | version = '0.0.1-SNAPSHOT' 4 | } 5 | ext { 6 | //docker 7 | imageName = dockerRepository + jar.baseName 8 | version = jar.version 9 | dockerBaseImage = 'anapsix/alpine-java:jre8' 10 | dockerExposePort = 8080 11 | } 12 | 13 | dependencies { 14 | compile("org.springframework.cloud:spring-cloud-starter-zuul") 15 | 16 | compile("org.webjars:jquery:3.0.0") 17 | compile("org.webjars:angularjs:1.5.7") 18 | compile("org.webjars.bower:angular-resource:1.5.7") 19 | compile("org.webjars:bootstrap:3.3.7") 20 | 21 | compile("org.springframework.session:spring-session") 22 | compile("org.springframework.boot:spring-boot-starter-data-redis") 23 | 24 | compile("org.springframework.boot:spring-boot-starter-security") 25 | compile("org.springframework.cloud:spring-cloud-starter-oauth2") 26 | compile("org.springframework.security.oauth:spring-security-oauth2") 27 | compile("org.springframework.security:spring-security-jwt") 28 | 29 | //required for deserializing jpa objects which are in the spring-session 30 | compile("org.hibernate.javax.persistence:hibernate-jpa-2.1-api:1.0.0.Final") 31 | compile("org.hibernate:hibernate-entitymanager:4.3.7.Final") 32 | 33 | compile("com.fasterxml.jackson.datatype:jackson-datatype-joda") 34 | } 35 | -------------------------------------------------------------------------------- /microservices/edge/docker-entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | CONTAINER_IP='http://rancher-metadata.rancher.internal/latest/self/container/primary_ip' 4 | 5 | STATUS_CODE=$(curl --write-out %{http_code} --silent --output /dev/null ${CONTAINER_IP}) 6 | 7 | if [ "$STATUS_CODE" -eq "200" ] ; then 8 | EUREKA_INSTANCE_HOSTNAME=$(curl http://rancher-metadata.rancher.internal/latest/self/container/primary_ip) 9 | echo "Instance hostname: " . $EUREKA_INSTANCE_HOSTNAME 10 | exec java -jar -Djava.security.egd=file:/dev/./urandom -Dspring.profiles.active=docker -Deureka.instance.preferIpAddress=true -Deureka.instance.ipAddress=$EUREKA_INSTANCE_HOSTNAME -Deureka.instance.hostname=$EUREKA_INSTANCE_HOSTNAME /app.jar 11 | else 12 | exec java -jar -Djava.security.egd=file:/dev/./urandom -Dspring.profiles.active=docker /app.jar 13 | fi 14 | -------------------------------------------------------------------------------- /microservices/edge/src/main/java/microservices4vaadin/auth/AcmeUser.java: -------------------------------------------------------------------------------- 1 | package microservices4vaadin.auth; 2 | 3 | import java.io.Serializable; 4 | import java.util.ArrayList; 5 | import java.util.List; 6 | 7 | import javax.validation.constraints.NotNull; 8 | 9 | import com.fasterxml.jackson.annotation.JsonIgnore; 10 | 11 | import lombok.Data; 12 | 13 | 14 | /** 15 | * Entity representing a user 16 | */ 17 | @Data 18 | public class AcmeUser implements Serializable { 19 | 20 | private static final long serialVersionUID = 5862624106931867852L; 21 | 22 | public AcmeUser() {} 23 | 24 | public AcmeUser(AcmeUser acmeUser) { 25 | super(); 26 | this.itemId = acmeUser.itemId; 27 | this.email = acmeUser.email; 28 | this.password = acmeUser.password; 29 | this.activated = acmeUser.activated; 30 | this.activationKey = acmeUser.activationKey; 31 | this.authorities = acmeUser.authorities; 32 | } 33 | 34 | private long itemId; 35 | 36 | @NotNull 37 | private String email; 38 | 39 | private String password; 40 | 41 | boolean activated = false; 42 | 43 | private String activationKey; 44 | 45 | @JsonIgnore 46 | private List authorities = new ArrayList(); 47 | 48 | } 49 | -------------------------------------------------------------------------------- /microservices/edge/src/main/java/microservices4vaadin/auth/AcmeUserDetails.java: -------------------------------------------------------------------------------- 1 | package microservices4vaadin.auth; 2 | 3 | import lombok.Data; 4 | import lombok.EqualsAndHashCode; 5 | 6 | import org.springframework.security.core.userdetails.UserDetails; 7 | 8 | /** 9 | * User Details implementation for an AcmeUser 10 | */ 11 | @Data 12 | @EqualsAndHashCode(callSuper=true) 13 | public class AcmeUserDetails extends AcmeUser implements UserDetails { 14 | 15 | private static final long serialVersionUID = -2841246955880250736L; 16 | 17 | public AcmeUserDetails(){ 18 | 19 | } 20 | 21 | public AcmeUserDetails(AcmeUser acmeUser) { 22 | super(acmeUser); 23 | } 24 | 25 | @Override 26 | public String getUsername() { 27 | return getEmail(); 28 | } 29 | 30 | @Override 31 | public boolean isAccountNonExpired() { 32 | return true; 33 | } 34 | 35 | @Override 36 | public boolean isAccountNonLocked() { 37 | return true; 38 | } 39 | 40 | @Override 41 | public boolean isCredentialsNonExpired() { 42 | return true; 43 | } 44 | 45 | @Override 46 | public boolean isEnabled() { 47 | return isActivated(); 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /microservices/edge/src/main/java/microservices4vaadin/auth/Authority.java: -------------------------------------------------------------------------------- 1 | package microservices4vaadin.auth; 2 | 3 | import java.io.Serializable; 4 | 5 | import javax.validation.constraints.NotNull; 6 | 7 | import lombok.Data; 8 | 9 | import org.springframework.security.core.GrantedAuthority; 10 | import org.springframework.security.core.authority.SimpleGrantedAuthority; 11 | 12 | 13 | /** 14 | * Defines the granted authorities currently held by an AcmeUser 15 | */ 16 | @Data 17 | public class Authority implements GrantedAuthority, Serializable { 18 | 19 | private static final long serialVersionUID = -3022031591212475416L; 20 | 21 | private long itemId; 22 | 23 | @NotNull 24 | private String name; 25 | 26 | @Override 27 | public String getAuthority() { 28 | return new SimpleGrantedAuthority(name).getAuthority(); 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /microservices/edge/src/main/java/microservices4vaadin/edge/CorrectHeadersFilter.java: -------------------------------------------------------------------------------- 1 | package microservices4vaadin.edge; 2 | 3 | import java.util.List; 4 | import java.util.Set; 5 | 6 | import org.springframework.core.annotation.Order; 7 | import org.springframework.stereotype.Component; 8 | 9 | import com.netflix.util.Pair; 10 | import com.netflix.zuul.ZuulFilter; 11 | import com.netflix.zuul.context.RequestContext; 12 | 13 | @Order(2) 14 | @Component 15 | @SuppressWarnings("unchecked") 16 | public class CorrectHeadersFilter extends ZuulFilter { 17 | 18 | @Override 19 | public String filterType() { 20 | return "pre"; 21 | } 22 | 23 | @Override 24 | public int filterOrder() { 25 | return 10000; 26 | } 27 | 28 | @Override 29 | public boolean shouldFilter() { 30 | return true; 31 | } 32 | 33 | @Override 34 | public Object run() { 35 | RequestContext currentContext = RequestContext.getCurrentContext(); 36 | 37 | currentContext.addZuulRequestHeader("host", currentContext.getRequest() 38 | .getHeader("host")); 39 | 40 | // XXX 41 | List> responseHeaders = currentContext.getZuulResponseHeaders(); 42 | responseHeaders.remove("x-forwarded-prefix"); 43 | 44 | ((Set) currentContext.get("ignoredHeaders")).clear();// XXX 45 | return null; 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /microservices/edge/src/main/java/microservices4vaadin/edge/ZuulApplication.java: -------------------------------------------------------------------------------- 1 | package microservices4vaadin.edge; 2 | 3 | import org.apache.catalina.connector.Connector; 4 | import org.springframework.boot.SpringApplication; 5 | import org.springframework.boot.autoconfigure.SpringBootApplication; 6 | import org.springframework.boot.autoconfigure.domain.EntityScan; 7 | import org.springframework.boot.context.embedded.EmbeddedServletContainerFactory; 8 | import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory; 9 | import org.springframework.cloud.netflix.zuul.EnableZuulProxy; 10 | import org.springframework.context.annotation.Bean; 11 | 12 | @SpringBootApplication 13 | @EntityScan(basePackages ={ "microservices4vaadin.auth" }) 14 | @EnableZuulProxy 15 | public class ZuulApplication { 16 | 17 | @Bean 18 | public EmbeddedServletContainerFactory servletContainer() { 19 | TomcatEmbeddedServletContainerFactory tomcat = new TomcatEmbeddedServletContainerFactory(); 20 | tomcat.addAdditionalTomcatConnectors(createStandardConnector()); 21 | return tomcat; 22 | } 23 | 24 | private Connector createStandardConnector() { 25 | Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol"); 26 | connector.setPort(80); 27 | return connector; 28 | } 29 | 30 | public static void main(String[] args) { 31 | SpringApplication.run(ZuulApplication.class, args); 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /microservices/edge/src/main/java/microservices4vaadin/edge/config/CORSFilter.java: -------------------------------------------------------------------------------- 1 | package microservices4vaadin.edge.config; 2 | 3 | import java.io.IOException; 4 | 5 | import javax.servlet.Filter; 6 | import javax.servlet.FilterChain; 7 | import javax.servlet.FilterConfig; 8 | import javax.servlet.ServletException; 9 | import javax.servlet.ServletRequest; 10 | import javax.servlet.ServletResponse; 11 | import javax.servlet.http.HttpServletResponse; 12 | 13 | import org.springframework.stereotype.Component; 14 | 15 | @Component 16 | public class CORSFilter implements Filter { 17 | 18 | @Override 19 | public void init(FilterConfig filterConfig) throws ServletException { 20 | } 21 | 22 | @Override 23 | public void doFilter(ServletRequest request, ServletResponse res, FilterChain chain) throws IOException, ServletException { 24 | HttpServletResponse response = (HttpServletResponse) res; 25 | response.setHeader("Access-Control-Allow-Origin", "*"); 26 | response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE"); 27 | response.setHeader("Access-Control-Max-Age", "3600"); 28 | response.setHeader("Access-Control-Allow-Headers", "Accept, Content-Type,x-requested-with,x-auth-token,x-xsrf-token"); 29 | chain.doFilter(request, response); 30 | } 31 | 32 | public void destroy() {} 33 | 34 | } -------------------------------------------------------------------------------- /microservices/edge/src/main/java/microservices4vaadin/edge/config/CustomAuthenticationEntryPoint.java: -------------------------------------------------------------------------------- 1 | package microservices4vaadin.edge.config; 2 | 3 | import java.io.IOException; 4 | 5 | import javax.servlet.http.HttpServletRequest; 6 | import javax.servlet.http.HttpServletResponse; 7 | 8 | import org.springframework.security.core.AuthenticationException; 9 | import org.springframework.security.web.AuthenticationEntryPoint; 10 | import org.springframework.stereotype.Component; 11 | 12 | @Component 13 | public class CustomAuthenticationEntryPoint implements AuthenticationEntryPoint { 14 | 15 | private final String HOME_PAGE = "/"; 16 | 17 | @Override 18 | public void commence(HttpServletRequest request, HttpServletResponse response, 19 | AuthenticationException authException ) throws IOException{ 20 | String method = request.getMethod(); 21 | String servletPath = request.getServletPath(); 22 | 23 | if (method.equals("GET") && servletPath.equals("/uaa/login")) 24 | response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized"); 25 | else 26 | response.sendRedirect(HOME_PAGE); 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /microservices/edge/src/main/java/microservices4vaadin/edge/config/CustomLogoutSuccessHandler.java: -------------------------------------------------------------------------------- 1 | package microservices4vaadin.edge.config; 2 | 3 | import java.io.IOException; 4 | 5 | import javax.servlet.ServletException; 6 | import javax.servlet.http.HttpServletRequest; 7 | import javax.servlet.http.HttpServletResponse; 8 | 9 | import org.springframework.security.core.Authentication; 10 | import org.springframework.security.web.authentication.logout.LogoutSuccessHandler; 11 | import org.springframework.security.web.authentication.logout.SimpleUrlLogoutSuccessHandler; 12 | import org.springframework.stereotype.Component; 13 | 14 | @Component 15 | public class CustomLogoutSuccessHandler implements LogoutSuccessHandler { 16 | 17 | //public final static String DEFAULT_TARGET_URL = "https://localhost:8443"; 18 | 19 | @Override 20 | public void onLogoutSuccess( HttpServletRequest request, 21 | HttpServletResponse response, Authentication authentication ) 22 | throws IOException, ServletException { 23 | SimpleUrlLogoutSuccessHandler logoutSuccessHandler = new SimpleUrlLogoutSuccessHandler(); 24 | //TODO: indicate logout and present special logout site 25 | logoutSuccessHandler.setDefaultTargetUrl( "/" ); 26 | logoutSuccessHandler.onLogoutSuccess( request, response, authentication ); 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /microservices/edge/src/main/java/microservices4vaadin/edge/config/SecurityConfiguration.java: -------------------------------------------------------------------------------- 1 | package microservices4vaadin.edge.config; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.boot.autoconfigure.security.SecurityProperties; 5 | import org.springframework.boot.autoconfigure.security.oauth2.client.EnableOAuth2Sso; 6 | import org.springframework.context.annotation.Bean; 7 | import org.springframework.context.annotation.Configuration; 8 | import org.springframework.core.annotation.Order; 9 | import org.springframework.security.config.annotation.web.builders.HttpSecurity; 10 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; 11 | import org.springframework.security.web.authentication.logout.LogoutSuccessHandler; 12 | 13 | @Configuration 14 | @EnableOAuth2Sso 15 | @Order(SecurityProperties.ACCESS_OVERRIDE_ORDER) 16 | public class SecurityConfiguration extends WebSecurityConfigurerAdapter { 17 | 18 | @Autowired 19 | private CustomAuthenticationEntryPoint customAuthenticationEntryPoint; 20 | 21 | @Bean 22 | public LogoutSuccessHandler logoutSuccessHandler() { 23 | return new CustomLogoutSuccessHandler(); 24 | } 25 | 26 | @Override 27 | protected void configure(HttpSecurity http) throws Exception { 28 | http.portMapper().http(80).mapsTo(443); 29 | 30 | http.exceptionHandling().authenticationEntryPoint(customAuthenticationEntryPoint); 31 | 32 | http.headers().frameOptions().disable(); 33 | 34 | http.logout().logoutSuccessHandler(logoutSuccessHandler()).permitAll() 35 | .and() 36 | .antMatcher("/**").authorizeRequests() 37 | .antMatchers("/webjars/**", "/", "/index.html", "/empty.html", "/login.html").permitAll() 38 | .antMatchers("/authserver/uaa/login", "/authserver/uaa/register", "/authserver/uaa/activate").permitAll() 39 | .antMatchers("/ui/VAADIN/**").permitAll() 40 | .anyRequest().authenticated() 41 | .and().csrf().disable().requiresChannel().anyRequest().requiresSecure(); 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /microservices/edge/src/main/java/microservices4vaadin/edge/config/SessionConfiguration.java: -------------------------------------------------------------------------------- 1 | package microservices4vaadin.edge.config; 2 | 3 | import org.springframework.beans.factory.BeanFactory; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.beans.factory.support.DefaultListableBeanFactory; 6 | import org.springframework.context.ApplicationContext; 7 | import org.springframework.context.annotation.Bean; 8 | import org.springframework.context.annotation.Configuration; 9 | import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession; 10 | import org.springframework.session.web.http.CookieHttpSessionStrategy; 11 | import org.springframework.session.web.http.DefaultCookieSerializer; 12 | import org.springframework.session.web.http.HttpSessionStrategy; 13 | 14 | @Configuration 15 | @EnableRedisHttpSession 16 | public class SessionConfiguration { 17 | 18 | private final static String SESSION_SERIALIZATION_ID = "microservices4vaadin"; 19 | 20 | @Autowired 21 | private ApplicationContext appContext; 22 | 23 | @Bean 24 | public String overwriteSerializationId() { 25 | BeanFactory beanFactory = appContext.getAutowireCapableBeanFactory(); 26 | ((DefaultListableBeanFactory) beanFactory).setSerializationId(SESSION_SERIALIZATION_ID); 27 | return "overwritten"; 28 | } 29 | 30 | @Bean 31 | public HttpSessionStrategy httpSessionStrategy() { 32 | CookieHttpSessionStrategy cookieHttpSessionStrategy = new CookieHttpSessionStrategy(); 33 | DefaultCookieSerializer cookieSerializer = new DefaultCookieSerializer(); 34 | cookieSerializer.setCookieName("JSESSIONID"); 35 | cookieSerializer.setCookiePath("/"); 36 | cookieSerializer.setDomainNamePattern("^.+?\\.(\\w+\\.[a-z]+)$"); 37 | cookieHttpSessionStrategy.setCookieSerializer(cookieSerializer); 38 | return cookieHttpSessionStrategy; 39 | } 40 | 41 | @Bean 42 | public SessionSerializer springSessionDefaultRedisSerializer() { 43 | return new SessionSerializer(); 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /microservices/edge/src/main/java/microservices4vaadin/edge/config/SessionSerializer.java: -------------------------------------------------------------------------------- 1 | package microservices4vaadin.edge.config; 2 | 3 | import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer; 4 | import org.springframework.data.redis.serializer.SerializationException; 5 | 6 | //@Slf4j 7 | public class SessionSerializer extends JdkSerializationRedisSerializer { 8 | 9 | @Override 10 | public Object deserialize(byte[] bytes) { 11 | try { 12 | Object obj = super.deserialize(bytes); 13 | return obj; 14 | } 15 | catch (SerializationException se) { 16 | // whenever inexistent classes from other service are deserialized they end up here 17 | //log.debug("Ignore: ", se.getRootCause()); 18 | } 19 | 20 | return null; 21 | } 22 | 23 | @Override 24 | public byte[] serialize(Object object) { 25 | return super.serialize(object); 26 | } 27 | 28 | } -------------------------------------------------------------------------------- /microservices/edge/src/main/java/microservices4vaadin/edge/exception/UserNotActivatedException.java: -------------------------------------------------------------------------------- 1 | package microservices4vaadin.edge.exception; 2 | 3 | import org.springframework.security.core.AuthenticationException; 4 | 5 | /** 6 | * Thrown when the user attempting to authenticate is not activated 7 | */ 8 | public class UserNotActivatedException extends AuthenticationException{ 9 | 10 | private static final long serialVersionUID = 7485453242456652318L; 11 | 12 | public UserNotActivatedException(String msg) { 13 | super(msg); 14 | // TODO Auto-generated constructor stub 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /microservices/edge/src/main/java/microservices4vaadin/edge/exception/UserNotFoundException.java: -------------------------------------------------------------------------------- 1 | package microservices4vaadin.edge.exception; 2 | 3 | import org.springframework.security.core.AuthenticationException; 4 | 5 | /** 6 | * Thrown when the provided username is not found 7 | */ 8 | public class UserNotFoundException extends AuthenticationException { 9 | 10 | private static final long serialVersionUID = 6587656019426094542L; 11 | 12 | public UserNotFoundException(String msg) { 13 | super(msg); 14 | // TODO Auto-generated constructor stub 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /microservices/edge/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 443 3 | use-forward-headers: true 4 | ssl: 5 | key-store: classpath:keystore.jks 6 | key-store-password: example 7 | key-password: example 8 | 9 | ribbon: 10 | restclient.enabled: true 11 | TrustStore: keystore.jks 12 | TrustStorePassword : example 13 | ReadTimeout: 60000 14 | IsSecure: true 15 | MaxAutoRetries: 2 16 | 17 | spring: 18 | redis: 19 | host: localhost 20 | port: 6379 21 | 22 | zuul: 23 | add-proxy-headers: true 24 | debug: 25 | request: true 26 | routes: 27 | authserver: 28 | path: /authserver/** 29 | serviceId: authserver 30 | user: 31 | path: /user/** 32 | url: https://localhost:443/authserver/uaa/user 33 | register: 34 | path: /register/** 35 | url: https://localhost:443/authserver/uaa/register 36 | frontend1: 37 | path: /ui/** 38 | serviceId: frontend 39 | stripPrefix: false 40 | frontend2: 41 | path: /frontend/** 42 | serviceId: frontend 43 | 44 | eureka: 45 | client: 46 | serviceUrl: 47 | defaultZone: http://${eureka.host:localhost}:${eureka.port:8761}/eureka/ 48 | 49 | hystrix: 50 | command: 51 | frontend: 52 | execution: 53 | isolation: 54 | thread: 55 | timeoutInMilliseconds: 60000 56 | authserver: 57 | execution: 58 | isolation: 59 | thread: 60 | timeoutInMilliseconds: 60000 61 | 62 | management: 63 | security: 64 | enabled: false 65 | security: 66 | basic: 67 | enabled: false 68 | user: 69 | password: none 70 | oauth2: 71 | resource: 72 | userInfoUri: https://localhost:443/uaa/user 73 | 74 | logging: 75 | level: 76 | org.springframework.boot: INFO 77 | org.springframework.session: INFO 78 | org.springframework.security: INFO 79 | org.springframework.web: INFO 80 | com.netflix.discovery: 'OFF' 81 | 82 | --- 83 | # For deployment in Docker containers 84 | spring: 85 | profiles: docker 86 | redis: 87 | host: redis 88 | 89 | security: 90 | oauth2: 91 | resource: 92 | userInfoUri: https://localhost:443/uaa/user 93 | -------------------------------------------------------------------------------- /microservices/edge/src/main/resources/bootstrap.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: edge 4 | cloud: 5 | config: 6 | uri: http://localhost:8888 7 | 8 | --- 9 | # For deployment in Docker containers 10 | spring: 11 | profiles: docker 12 | cloud: 13 | config: 14 | uri: http://192.168.59.103:8888 15 | -------------------------------------------------------------------------------- /microservices/edge/src/main/resources/keystore.jks: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khauser/microservices4vaadin/05aab5a8ee0484004bd3368184c617c2853c86be/microservices/edge/src/main/resources/keystore.jks -------------------------------------------------------------------------------- /microservices/edge/src/main/resources/static/empty.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khauser/microservices4vaadin/05aab5a8ee0484004bd3368184c617c2853c86be/microservices/edge/src/main/resources/static/empty.html -------------------------------------------------------------------------------- /microservices/edge/src/main/resources/static/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | microservices4vaadin 5 | 6 | 9 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /microservices/edge/src/main/wro/main.less: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khauser/microservices4vaadin/05aab5a8ee0484004bd3368184c617c2853c86be/microservices/edge/src/main/wro/main.less -------------------------------------------------------------------------------- /microservices/edge/src/main/wro/wro.properties: -------------------------------------------------------------------------------- 1 | #List of preProcessors 2 | preProcessors=lessCssImport 3 | #List of postProcessors 4 | postProcessors=less4j,jsMin -------------------------------------------------------------------------------- /microservices/edge/src/main/wro/wro.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | webjar:bootstrap/3.2.0/less/bootstrap.less 4 | file:${project.basedir}/src/main/wro/main.less 5 | webjar:jquery/2.1.1/jquery.js 6 | webjar:angularjs/1.3.8/angular.js 7 | webjar:angularjs/1.3.8/angular-route.js 8 | 9 | -------------------------------------------------------------------------------- /microservices/edge/src/test/java/microservices4vaadin/edge/ApplicationTests.java: -------------------------------------------------------------------------------- 1 | package microservices4vaadin.edge; 2 | 3 | //import static org.junit.Assert.assertEquals; 4 | //import static org.junit.Assert.assertTrue; 5 | //import lessor.edge.ZuulApplication; 6 | // 7 | //import org.junit.Test; 8 | //import org.junit.runner.RunWith; 9 | //import org.springframework.beans.factory.annotation.Value; 10 | //import org.springframework.boot.test.IntegrationTest; 11 | //import org.springframework.boot.test.SpringApplicationConfiguration; 12 | //import org.springframework.boot.test.TestRestTemplate; 13 | //import org.springframework.http.HttpStatus; 14 | //import org.springframework.http.ResponseEntity; 15 | //import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 16 | //import org.springframework.test.context.web.WebAppConfiguration; 17 | //import org.springframework.web.client.RestTemplate; 18 | // 19 | //@RunWith(SpringJUnit4ClassRunner.class) 20 | //@SpringApplicationConfiguration(classes = ZuulApplication.class) 21 | //@WebAppConfiguration 22 | //@IntegrationTest("server.port:0") 23 | //public class ApplicationTests { 24 | // 25 | // @Value("${local.server.port}") 26 | // private int port; 27 | // 28 | // @Value("${security.oauth2.client.userAuthorizationUri}") 29 | // private String authorizeUri; 30 | // 31 | // private RestTemplate template = new TestRestTemplate(); 32 | 33 | // @Test 34 | // public void homePageLoads() { 35 | // ResponseEntity response = template.getForEntity("http://localhost:" 36 | // + port + "/", String.class); 37 | // //assertEquals(HttpStatus.FOUND, response.getStatusCode()); 38 | // } 39 | // 40 | // @Test 41 | // public void userEndpointProtected() { 42 | // ResponseEntity response = template.getForEntity("http://localhost:" 43 | // + port + "/user", String.class); 44 | // assertEquals(HttpStatus.FOUND, response.getStatusCode()); 45 | // assertEquals("http://localhost:" + port + "/login", response.getHeaders() 46 | // .getLocation().toString()); 47 | // } 48 | // 49 | //// @Test 50 | //// public void resourceEndpointProtected() { 51 | //// ResponseEntity response = template.getForEntity("http://localhost:" 52 | //// + port + "/resource", String.class); 53 | //// assertEquals(HttpStatus.FOUND, response.getStatusCode()); 54 | //// assertEquals("http://localhost:" + port + "/login", response.getHeaders() 55 | //// .getLocation().toString()); 56 | //// } 57 | // 58 | // @Test 59 | // public void loginRedirects() { 60 | // ResponseEntity response = template.getForEntity("http://localhost:" 61 | // + port + "/login", String.class); 62 | // assertEquals(HttpStatus.FOUND, response.getStatusCode()); 63 | // String location = response.getHeaders().getFirst("Location"); 64 | // assertTrue("Wrong location: " + location, location.startsWith(authorizeUri)); 65 | // } 66 | // 67 | //} -------------------------------------------------------------------------------- /microservices/eventstore/.gitignore: -------------------------------------------------------------------------------- 1 | .classpath 2 | .gradle/ 3 | .project 4 | .settings/ 5 | build/ 6 | /bin/ 7 | *.cache 8 | -------------------------------------------------------------------------------- /microservices/eventstore/build.gradle: -------------------------------------------------------------------------------- 1 | jar { 2 | baseName = 'eventstore' 3 | version = '0.0.1-SNAPSHOT' 4 | } 5 | 6 | ext { 7 | axonVersion = "2.4.3" 8 | 9 | //docker 10 | imageName = dockerRepository + jar.baseName 11 | version = jar.version 12 | dockerBaseImage = 'anapsix/alpine-java:jre8' 13 | dockerExposePort = 6666 14 | } 15 | 16 | dependencies { 17 | compile project(":common") 18 | 19 | compile("org.axonframework:axon-amqp:${axonVersion}") 20 | compile("org.axonframework:axon-mongo:${axonVersion}") 21 | compile("org.springframework.boot:spring-boot-starter-amqp:${springBootVersion}") 22 | compile("org.springframework.boot:spring-boot-starter-data-mongodb:${springBootVersion}") 23 | compile("org.mongodb:mongo-java-driver:2.14.3") 24 | 25 | compile("org.hibernate.javax.persistence:hibernate-jpa-2.1-api:1.0.0.Final") 26 | 27 | testCompile("org.axonframework:axon-test:2.4.3") 28 | } 29 | -------------------------------------------------------------------------------- /microservices/eventstore/docker-entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | CONTAINER_IP='http://rancher-metadata.rancher.internal/latest/self/container/primary_ip' 4 | 5 | STATUS_CODE=$(curl --write-out %{http_code} --silent --output /dev/null ${CONTAINER_IP}) 6 | 7 | if [ "$STATUS_CODE" -eq "200" ] ; then 8 | EUREKA_INSTANCE_HOSTNAME=$(curl http://rancher-metadata.rancher.internal/latest/self/container/primary_ip) 9 | echo "Instance hostname: " . $EUREKA_INSTANCE_HOSTNAME 10 | exec java -jar -Djava.security.egd=file:/dev/./urandom -Dspring.profiles.active=docker -Deureka.instance.preferIpAddress=true -Deureka.instance.ipAddress=$EUREKA_INSTANCE_HOSTNAME -Deureka.instance.hostname=$EUREKA_INSTANCE_HOSTNAME /app.jar 11 | else 12 | exec java -jar -Djava.security.egd=file:/dev/./urandom -Dspring.profiles.active=docker /app.jar 13 | fi 14 | -------------------------------------------------------------------------------- /microservices/eventstore/src/main/java/microservices4vaadin/eventstore/EventStoreApplication.java: -------------------------------------------------------------------------------- 1 | package microservices4vaadin.eventstore; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.cloud.client.discovery.EnableDiscoveryClient; 6 | 7 | @SpringBootApplication 8 | @EnableDiscoveryClient 9 | public class EventStoreApplication { 10 | 11 | public static void main(String[] args) { 12 | SpringApplication.run(EventStoreApplication.class, args); 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /microservices/eventstore/src/main/java/microservices4vaadin/eventstore/aggregate/UserAggregate.java: -------------------------------------------------------------------------------- 1 | package microservices4vaadin.eventstore.aggregate; 2 | 3 | import org.axonframework.commandhandling.annotation.CommandHandler; 4 | import org.axonframework.eventsourcing.annotation.AbstractAnnotatedAggregateRoot; 5 | import org.axonframework.eventsourcing.annotation.AggregateIdentifier; 6 | import org.axonframework.eventsourcing.annotation.EventSourcingHandler; 7 | 8 | import lombok.Getter; 9 | import lombok.extern.slf4j.Slf4j; 10 | import microservices4vaadin.eventstore.command.CreateUserCommand; 11 | import microservices4vaadin.userevents.UserCreatedEvent; 12 | 13 | @Slf4j 14 | @Getter 15 | public class UserAggregate extends AbstractAnnotatedAggregateRoot { 16 | 17 | private static final long serialVersionUID = 198894074441714656L; 18 | 19 | @AggregateIdentifier 20 | private Long id; 21 | private String email; 22 | private String firstName; 23 | private String lastName; 24 | 25 | public UserAggregate() { 26 | } 27 | 28 | @CommandHandler 29 | public UserAggregate(CreateUserCommand command) { 30 | log.debug("Command: 'CreateUserCommand' received."); 31 | log.debug("Queuing up a new UserCreatedEvent for user '{}'", command.getId()); 32 | 33 | UserCreatedEvent user = new UserCreatedEvent(); 34 | user.setId(command.getId()); 35 | user.setEmail(command.getName()); 36 | user.setFirstName(command.getFirstName()); 37 | user.setLastName(command.getLastName()); 38 | apply(user); 39 | } 40 | 41 | // @CommandHandler 42 | // public void markActivated(ActivateUserCommand command) { 43 | // log.debug("Command: 'ActivateUserCommand' received."); 44 | // if (!this.isActivated()) { 45 | // apply(new UserActivatedEvent(id, name)); 46 | // } else { 47 | // throw new IllegalStateException("This UserAggregate (" + this.getId() + ") is already activated."); 48 | // } 49 | // } 50 | 51 | // @CommandHandler 52 | // public void markUnsaleable(MarkProductAsUnsaleableCommand command) { 53 | // LOG.debug("Command: 'MarkProductAsUnsaleableCommand' received."); 54 | // if (this.isSaleable()) { 55 | // apply(new ProductUnsaleableEvent(id)); 56 | // } else { 57 | // throw new IllegalStateException("This ProductAggregate (" + this.getId() + ") is already off-sale."); 58 | // } 59 | // } 60 | 61 | @EventSourcingHandler 62 | public void on(UserCreatedEvent event) { 63 | this.id = event.getId(); 64 | this.email = event.getEmail(); 65 | this.firstName = event.getFirstName(); 66 | this.lastName = event.getLastName(); 67 | log.debug("Applied: 'UserCreatedEvent' [{}] '{}'", event.getId(), event.getEmail()); 68 | } 69 | 70 | // @EventSourcingHandler 71 | // public void on(UserActivatedEvent event) { 72 | // this.isActivated = true; 73 | // log.debug("Applied: 'UserActivatedEvent' [{}]", event.getId()); 74 | // } 75 | 76 | } 77 | -------------------------------------------------------------------------------- /microservices/eventstore/src/main/java/microservices4vaadin/eventstore/command/ActivateUserCommand.java: -------------------------------------------------------------------------------- 1 | package microservices4vaadin.eventstore.command; 2 | 3 | import org.axonframework.commandhandling.annotation.TargetAggregateIdentifier; 4 | 5 | import lombok.Getter; 6 | 7 | @Getter 8 | public class ActivateUserCommand { 9 | 10 | @TargetAggregateIdentifier 11 | private final Long id; 12 | private final String name; 13 | 14 | public ActivateUserCommand(Long id, String name) { 15 | this.id = id; 16 | this.name = name; 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /microservices/eventstore/src/main/java/microservices4vaadin/eventstore/command/CreateUserCommand.java: -------------------------------------------------------------------------------- 1 | package microservices4vaadin.eventstore.command; 2 | 3 | import org.axonframework.commandhandling.annotation.TargetAggregateIdentifier; 4 | 5 | import lombok.Getter; 6 | 7 | @Getter 8 | public class CreateUserCommand { 9 | 10 | @TargetAggregateIdentifier 11 | private final Long id; 12 | private final String name; 13 | private final String firstName; 14 | private final String lastName; 15 | 16 | public CreateUserCommand(Long id, String name, String firstName, String lastName) { 17 | this.id = id; 18 | this.name = name; 19 | this.firstName = firstName; 20 | this.lastName = lastName; 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /microservices/eventstore/src/main/java/microservices4vaadin/eventstore/command/DeleteUserCommand.java: -------------------------------------------------------------------------------- 1 | package microservices4vaadin.eventstore.command; 2 | 3 | public class DeleteUserCommand { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /microservices/eventstore/src/main/java/microservices4vaadin/eventstore/configuration/RabbitConfiguration.java: -------------------------------------------------------------------------------- 1 | package microservices4vaadin.eventstore.configuration; 2 | 3 | import org.springframework.amqp.core.Binding; 4 | import org.springframework.amqp.core.FanoutExchange; 5 | import org.springframework.amqp.core.Queue; 6 | import org.springframework.amqp.rabbit.connection.CachingConnectionFactory; 7 | import org.springframework.amqp.rabbit.connection.ConnectionFactory; 8 | import org.springframework.amqp.rabbit.core.RabbitAdmin; 9 | import org.springframework.amqp.rabbit.transaction.RabbitTransactionManager; 10 | import org.springframework.beans.factory.annotation.Required; 11 | import org.springframework.beans.factory.annotation.Value; 12 | import org.springframework.context.annotation.Bean; 13 | import org.springframework.context.annotation.Configuration; 14 | 15 | /** 16 | * Created by ben on 23/02/16. 17 | */ 18 | @Configuration 19 | public class RabbitConfiguration { 20 | 21 | @Value("${spring.rabbitmq.hostname}") 22 | private String hostname; 23 | 24 | // @Value("${spring.rabbitmq.username}") 25 | // private String username; 26 | // 27 | // @Value("${spring.rabbitmq.password}") 28 | // private String password; 29 | 30 | @Value("${spring.application.exchange}") 31 | private String exchangeName; 32 | 33 | @Value("${spring.application.queue}") 34 | private String queueName; 35 | 36 | @Bean 37 | Queue defaultStream() { 38 | return new Queue(queueName, true); 39 | } 40 | 41 | @Bean 42 | FanoutExchange eventBusExchange() { 43 | return new FanoutExchange(exchangeName, true, false); 44 | } 45 | 46 | @Bean 47 | Binding binding() { 48 | return new Binding(queueName, Binding.DestinationType.QUEUE, exchangeName, "*.*", null); 49 | } 50 | 51 | @Bean 52 | ConnectionFactory connectionFactory() { 53 | CachingConnectionFactory connectionFactory = new CachingConnectionFactory(hostname); 54 | return connectionFactory; 55 | } 56 | 57 | @Bean 58 | @Required 59 | RabbitAdmin rabbitAdmin() { 60 | RabbitAdmin admin = new RabbitAdmin(connectionFactory()); 61 | admin.setAutoStartup(true); 62 | admin.declareExchange(eventBusExchange()); 63 | admin.declareQueue(defaultStream()); 64 | admin.declareBinding(binding()); 65 | return admin; 66 | } 67 | 68 | @Bean 69 | RabbitTransactionManager transactionManager(){ 70 | RabbitTransactionManager txMgr = new RabbitTransactionManager(connectionFactory()); 71 | return txMgr; 72 | } 73 | 74 | } 75 | -------------------------------------------------------------------------------- /microservices/eventstore/src/main/java/microservices4vaadin/eventstore/controller/UserEventController.java: -------------------------------------------------------------------------------- 1 | package microservices4vaadin.eventstore.controller; 2 | 3 | import javax.servlet.http.HttpServletResponse; 4 | 5 | import org.axonframework.commandhandling.gateway.CommandGateway; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.http.HttpStatus; 8 | import org.springframework.http.ResponseEntity; 9 | import org.springframework.web.bind.annotation.RequestBody; 10 | import org.springframework.web.bind.annotation.RequestMapping; 11 | import org.springframework.web.bind.annotation.RequestMethod; 12 | import org.springframework.web.bind.annotation.RestController; 13 | 14 | import lombok.extern.slf4j.Slf4j; 15 | import microservices4vaadin.eventstore.command.CreateUserCommand; 16 | import microservices4vaadin.userevents.UserCreatedEvent; 17 | 18 | @RestController 19 | @RequestMapping("/user") 20 | @Slf4j 21 | public class UserEventController { 22 | 23 | @Autowired 24 | public CommandGateway commandGateway; 25 | 26 | @RequestMapping(value = "/createdEvent", method = RequestMethod.POST) 27 | public ResponseEntity publishCreatedEvent(@RequestBody(required = true) UserCreatedEvent userCreatedEvent, 28 | HttpServletResponse response) { 29 | 30 | log.debug("Adding User [{}] '{}'", userCreatedEvent.getId(), userCreatedEvent.getEmail()); 31 | CreateUserCommand command = new CreateUserCommand(userCreatedEvent.getId() 32 | , userCreatedEvent.getEmail(), userCreatedEvent.getFirstName(), userCreatedEvent.getLastName()); 33 | commandGateway.sendAndWait(command); 34 | log.info("Added User [{}] '{}'", userCreatedEvent.getId(), userCreatedEvent.getEmail()); 35 | response.setStatus(HttpServletResponse.SC_CREATED);// Set up the 201 CREATED response 36 | return new ResponseEntity("true", HttpStatus.CREATED); 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /microservices/eventstore/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 6666 3 | 4 | spring: 5 | application: 6 | name: eventstore 7 | exchange: user.events.fanout.exchange 8 | queue: user.default.queue 9 | databaseName: users 10 | eventsCollectionName: events 11 | snapshotCollectionName: snapshots 12 | rabbitmq: 13 | hostname: localhost 14 | data: 15 | mongodb: 16 | uri: mongodb://localhost:27017/users 17 | profiles: 18 | active: ${profile:default} 19 | 20 | logging: 21 | level: 22 | microservices4vaadin: INFO 23 | com.netflix.discovery: 'OFF' 24 | 25 | --- 26 | # For deployment in Docker containers 27 | spring: 28 | profiles: docker 29 | rabbitmq: 30 | hostname: rabbitmq 31 | data: 32 | mongodb: 33 | uri: mongodb://mongodb:27017/users 34 | -------------------------------------------------------------------------------- /microservices/eventstore/src/main/resources/bootstrap.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: eventstore 4 | cloud: 5 | config: 6 | uri: http://localhost:8888 7 | 8 | --- 9 | # For deployment in Docker containers 10 | spring: 11 | profiles: docker 12 | cloud: 13 | config: 14 | uri: http://192.168.59.103:8888 15 | -------------------------------------------------------------------------------- /microservices/eventstore/src/test/java/microservices4vaadin/eventstore/aggregate/UserAggregateTest.java: -------------------------------------------------------------------------------- 1 | package microservices4vaadin.eventstore.aggregate; 2 | 3 | import org.axonframework.test.FixtureConfiguration; 4 | import org.axonframework.test.Fixtures; 5 | import org.junit.Before; 6 | import org.junit.Test; 7 | 8 | import microservices4vaadin.eventstore.aggregate.UserAggregate; 9 | import microservices4vaadin.eventstore.command.CreateUserCommand; 10 | import microservices4vaadin.userevents.UserCreatedEvent; 11 | 12 | public class UserAggregateTest { 13 | 14 | private static final long EXPECTED_USER_ID = 1L; 15 | private static final String EXPECTED_USER_NAME = "UserName"; 16 | private static final String EXPECTED_FIRST_NAME = "Udo"; 17 | private static final String EXPECTED_LAST_NAME = "Lateck"; 18 | private FixtureConfiguration fixture; 19 | 20 | @Before 21 | public void setUp() throws Exception { 22 | fixture = Fixtures.newGivenWhenThenFixture(UserAggregate.class); 23 | } 24 | 25 | @Test 26 | public void testAddProduct() throws Exception { 27 | UserCreatedEvent user = new UserCreatedEvent(); 28 | user.setId(1L); 29 | user.setEmail(EXPECTED_USER_NAME); 30 | user.setFirstName(EXPECTED_FIRST_NAME); 31 | user.setLastName(EXPECTED_LAST_NAME); 32 | fixture.given() 33 | .when(new CreateUserCommand(EXPECTED_USER_ID, EXPECTED_USER_NAME, EXPECTED_FIRST_NAME, EXPECTED_LAST_NAME)) 34 | .expectEvents(user); 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /microservices/eventstore/src/test/java/microservices4vaadin/eventstore/controller/UserEventControllerTest.java: -------------------------------------------------------------------------------- 1 | package microservices4vaadin.eventstore.controller; 2 | 3 | import static org.junit.Assert.assertTrue; 4 | import static org.mockito.Matchers.any; 5 | import static org.mockito.Mockito.verify; 6 | import static org.mockito.Mockito.when; 7 | 8 | import javax.servlet.http.HttpServletResponse; 9 | 10 | import org.axonframework.commandhandling.gateway.CommandGateway; 11 | import org.junit.Before; 12 | import org.junit.Test; 13 | import org.mockito.Mock; 14 | import org.mockito.MockitoAnnotations; 15 | import org.springframework.mock.web.MockHttpServletResponse; 16 | 17 | import microservices4vaadin.eventstore.controller.UserEventController; 18 | import microservices4vaadin.userevents.UserCreatedEvent; 19 | 20 | public class UserEventControllerTest { 21 | 22 | UserEventController userEventController; 23 | MockHttpServletResponse mockHttpServletResponse; 24 | 25 | @Mock 26 | CommandGateway gateway; 27 | 28 | @Before 29 | public void setup() { 30 | MockitoAnnotations.initMocks(this); 31 | userEventController = new UserEventController(); 32 | mockHttpServletResponse = new MockHttpServletResponse(); 33 | } 34 | 35 | @Test 36 | public void testAddWithGoodRequestParams() { 37 | // Arrange 38 | userEventController.commandGateway = gateway; //cheating a bit here, but mocking all the axon framework's beans is a pain. 39 | when(gateway.sendAndWait(any())).thenReturn(null); 40 | 41 | UserCreatedEvent userCreatedEvent = new UserCreatedEvent(); 42 | userCreatedEvent.setId(1L); 43 | userCreatedEvent.setEmail("Test Create User"); 44 | //Act 45 | userEventController.publishCreatedEvent(userCreatedEvent, mockHttpServletResponse); 46 | 47 | //Assert 48 | verify(gateway).sendAndWait(any()); 49 | assertTrue(mockHttpServletResponse.getStatus() == HttpServletResponse.SC_CREATED); 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /microservices/frontend/.gitignore: -------------------------------------------------------------------------------- 1 | .classpath 2 | .gradle/ 3 | .project 4 | .settings/ 5 | build/ 6 | /bin/ 7 | *.cache 8 | -------------------------------------------------------------------------------- /microservices/frontend/build.gradle: -------------------------------------------------------------------------------- 1 | jar { 2 | baseName = 'frontend' 3 | version = '0.0.1-SNAPSHOT' 4 | } 5 | ext { 6 | //docker 7 | imageName = dockerRepository + jar.baseName 8 | version = jar.version 9 | dockerBaseImage = 'anapsix/alpine-java:jre8' 10 | dockerExposePort = 8081 11 | } 12 | 13 | ext { 14 | vaadinVersion = "8.3.0" 15 | vaadinSpringBootVersion = "2.0.1" 16 | jdalVaadinVersion = "2.0.0"; 17 | } 18 | 19 | dependencyManagement { 20 | imports { 21 | mavenBom "com.vaadin:vaadin-bom:${vaadinVersion}" 22 | } 23 | } 24 | 25 | dependencies { 26 | compile("com.vaadin:vaadin-spring-boot-starter:${vaadinSpringBootVersion}") 27 | 28 | compile("org.springframework.boot:spring-boot-starter-hateoas") 29 | 30 | compile("org.springframework.session:spring-session") 31 | compile("org.springframework.boot:spring-boot-starter-data-redis") 32 | 33 | compile("org.springframework.security.oauth:spring-security-oauth2") 34 | 35 | //required for deserializing jpa objects which are in the spring-session 36 | compile("org.hibernate.javax.persistence:hibernate-jpa-2.1-api:1.0.0.Final") 37 | compile("org.hibernate:hibernate-entitymanager:4.3.7.Final") 38 | 39 | compile("com.fasterxml.jackson.datatype:jackson-datatype-joda") 40 | 41 | compile("org.jdal:jdal-vaadin:${jdalVaadinVersion}") 42 | } 43 | -------------------------------------------------------------------------------- /microservices/frontend/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '2' 2 | 3 | services: 4 | redis: 5 | image: redis:4.0.2-alpine 6 | ports: 7 | - "6379:6379" 8 | -------------------------------------------------------------------------------- /microservices/frontend/docker-entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | CONTAINER_IP='http://rancher-metadata.rancher.internal/latest/self/container/primary_ip' 4 | 5 | STATUS_CODE=$(curl --write-out %{http_code} --silent --output /dev/null ${CONTAINER_IP}) 6 | 7 | if [ "$STATUS_CODE" -eq "200" ] ; then 8 | EUREKA_INSTANCE_HOSTNAME=$(curl http://rancher-metadata.rancher.internal/latest/self/container/primary_ip) 9 | echo "Instance hostname: " . $EUREKA_INSTANCE_HOSTNAME 10 | exec java -jar -Djava.security.egd=file:/dev/./urandom -Dspring.profiles.active=docker -Deureka.instance.preferIpAddress=true -Deureka.instance.ipAddress=$EUREKA_INSTANCE_HOSTNAME -Deureka.instance.hostname=$EUREKA_INSTANCE_HOSTNAME /app.jar 11 | else 12 | exec java -jar -Djava.security.egd=file:/dev/./urandom -Dspring.profiles.active=docker /app.jar 13 | fi 14 | -------------------------------------------------------------------------------- /microservices/frontend/launch/Lessor frontend (Development).launch: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /microservices/frontend/src/main/java/microservices4vaadin/auth/AcmeUser.java: -------------------------------------------------------------------------------- 1 | package microservices4vaadin.auth; 2 | 3 | import java.io.Serializable; 4 | import java.time.LocalDateTime; 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | import javax.persistence.Column; 9 | import javax.persistence.Entity; 10 | import javax.persistence.FetchType; 11 | import javax.persistence.GeneratedValue; 12 | import javax.persistence.GenerationType; 13 | import javax.persistence.Id; 14 | import javax.persistence.JoinColumn; 15 | import javax.persistence.JoinTable; 16 | import javax.persistence.ManyToMany; 17 | import javax.validation.constraints.NotNull; 18 | import javax.validation.constraints.Size; 19 | 20 | import org.hibernate.annotations.Type; 21 | import org.hibernate.validator.constraints.Email; 22 | import org.springframework.format.annotation.DateTimeFormat; 23 | 24 | import com.fasterxml.jackson.annotation.JsonIgnore; 25 | 26 | import lombok.Data; 27 | 28 | 29 | /** 30 | * Entity representing a user 31 | */ 32 | @Entity 33 | @Data 34 | public class AcmeUser implements Serializable { 35 | 36 | private static final long serialVersionUID = 5862624106931867852L; 37 | 38 | public AcmeUser() {} 39 | 40 | public AcmeUser(AcmeUser acmeUser) { 41 | super(); 42 | this.itemId = acmeUser.itemId; 43 | this.email = acmeUser.email; 44 | this.password = acmeUser.password; 45 | this.activated = acmeUser.activated; 46 | this.activationKey = acmeUser.activationKey; 47 | this.authorities = acmeUser.authorities; 48 | } 49 | 50 | @Id 51 | @GeneratedValue(strategy = GenerationType.AUTO) 52 | @Column(name = "id") 53 | private long itemId; 54 | 55 | @Email 56 | @NotNull 57 | @Size(min = 0, max = 100) 58 | @Column(length = 100, unique = true) 59 | private String email; 60 | 61 | @JsonIgnore 62 | @Size(min = 0, max = 100) 63 | @Column(length = 100) 64 | private String password; 65 | 66 | boolean activated = false; 67 | 68 | @Size(min = 0, max = 20) 69 | @Column(name = "activation_key", length = 20) 70 | @JsonIgnore 71 | private String activationKey; 72 | 73 | @ManyToMany(fetch = FetchType.EAGER) 74 | @JoinTable(name = "user_2_authority", 75 | joinColumns = @JoinColumn(name = "user_id", referencedColumnName = "id"), 76 | inverseJoinColumns = @JoinColumn(name = "authority_id", referencedColumnName = "id")) 77 | private List authorities = new ArrayList(); 78 | 79 | @NotNull 80 | @Column(nullable = false, length = 50, updatable = false) 81 | private String createdBy; 82 | 83 | @NotNull 84 | @Column(nullable = false) 85 | @Type(type = "org.jadira.usertype.dateandtime.threeten.PersistentLocalDateTime") 86 | @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") 87 | private LocalDateTime createdDateTime; 88 | 89 | } 90 | -------------------------------------------------------------------------------- /microservices/frontend/src/main/java/microservices4vaadin/auth/AcmeUserDetails.java: -------------------------------------------------------------------------------- 1 | package microservices4vaadin.auth; 2 | 3 | import lombok.Data; 4 | import lombok.EqualsAndHashCode; 5 | 6 | import org.springframework.security.core.userdetails.UserDetails; 7 | 8 | /** 9 | * User Details implementation for an AcmeUser 10 | */ 11 | @Data 12 | @EqualsAndHashCode(callSuper=true) 13 | public class AcmeUserDetails extends AcmeUser implements UserDetails { 14 | 15 | private static final long serialVersionUID = -2841246955880250736L; 16 | 17 | public AcmeUserDetails(){ 18 | 19 | } 20 | 21 | public AcmeUserDetails(AcmeUser acmeUser) { 22 | super(acmeUser); 23 | } 24 | 25 | @Override 26 | public String getUsername() { 27 | return getEmail(); 28 | } 29 | 30 | @Override 31 | public boolean isAccountNonExpired() { 32 | return true; 33 | } 34 | 35 | @Override 36 | public boolean isAccountNonLocked() { 37 | return true; 38 | } 39 | 40 | @Override 41 | public boolean isCredentialsNonExpired() { 42 | return true; 43 | } 44 | 45 | @Override 46 | public boolean isEnabled() { 47 | return isActivated(); 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /microservices/frontend/src/main/java/microservices4vaadin/auth/Authority.java: -------------------------------------------------------------------------------- 1 | package microservices4vaadin.auth; 2 | 3 | import java.io.Serializable; 4 | 5 | import javax.validation.constraints.NotNull; 6 | 7 | import lombok.Data; 8 | 9 | import org.springframework.security.core.GrantedAuthority; 10 | import org.springframework.security.core.authority.SimpleGrantedAuthority; 11 | 12 | 13 | /** 14 | * Defines the granted authorities currently held by an AcmeUser 15 | */ 16 | @Data 17 | public class Authority implements GrantedAuthority, Serializable { 18 | 19 | private static final long serialVersionUID = -3022031591212475416L; 20 | 21 | private long itemId; 22 | 23 | @NotNull 24 | private String name; 25 | 26 | @Override 27 | public String getAuthority() { 28 | return new SimpleGrantedAuthority(name).getAuthority(); 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /microservices/frontend/src/main/java/microservices4vaadin/frontend/VaadinApplication.java: -------------------------------------------------------------------------------- 1 | package microservices4vaadin.frontend; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.boot.autoconfigure.domain.EntityScan; 6 | import org.springframework.cloud.client.discovery.EnableDiscoveryClient; 7 | 8 | import com.vaadin.spring.annotation.EnableVaadin; 9 | 10 | import lombok.extern.slf4j.Slf4j; 11 | 12 | @SpringBootApplication 13 | @EntityScan(basePackages ={ "microservices4vaadin.auth" }) 14 | @EnableDiscoveryClient 15 | @Slf4j 16 | @EnableVaadin 17 | public class VaadinApplication { 18 | 19 | public static void main(String[] args) { 20 | log.info("Starting VaadinApplication"); 21 | SpringApplication.run(VaadinApplication.class, args); 22 | } 23 | 24 | } 25 | 26 | -------------------------------------------------------------------------------- /microservices/frontend/src/main/java/microservices4vaadin/frontend/config/RestClientConfiguration.java: -------------------------------------------------------------------------------- 1 | package microservices4vaadin.frontend.config; 2 | 3 | import java.security.KeyManagementException; 4 | import java.security.KeyStoreException; 5 | import java.security.NoSuchAlgorithmException; 6 | import java.security.cert.X509Certificate; 7 | 8 | import javax.net.ssl.SSLContext; 9 | 10 | import org.apache.http.conn.ssl.SSLConnectionSocketFactory; 11 | import org.apache.http.conn.ssl.TrustStrategy; 12 | import org.apache.http.impl.client.CloseableHttpClient; 13 | import org.apache.http.impl.client.HttpClients; 14 | import org.springframework.context.annotation.Bean; 15 | import org.springframework.context.annotation.Configuration; 16 | import org.springframework.hateoas.hal.Jackson2HalModule; 17 | import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; 18 | import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; 19 | import org.springframework.web.client.RestTemplate; 20 | 21 | import com.fasterxml.jackson.databind.DeserializationFeature; 22 | import com.fasterxml.jackson.databind.ObjectMapper; 23 | import com.fasterxml.jackson.databind.SerializationFeature; 24 | 25 | @Configuration 26 | public class RestClientConfiguration { 27 | 28 | @Bean 29 | public RestTemplate restTemplate() { 30 | TrustStrategy acceptingTrustStrategy = (X509Certificate[] chain, String authType) -> true; 31 | 32 | try { 33 | SSLContext sslContext = org.apache.http.ssl.SSLContexts.custom() 34 | .loadTrustMaterial(null, acceptingTrustStrategy) 35 | .build(); 36 | 37 | 38 | SSLConnectionSocketFactory csf = new SSLConnectionSocketFactory(sslContext); 39 | 40 | CloseableHttpClient httpClient = HttpClients.custom() 41 | .setSSLSocketFactory(csf) 42 | .build(); 43 | 44 | HttpComponentsClientHttpRequestFactory requestFactory = 45 | new HttpComponentsClientHttpRequestFactory(); 46 | 47 | requestFactory.setHttpClient(httpClient); 48 | 49 | 50 | RestTemplate restTemplate = new RestTemplate(requestFactory); 51 | restTemplate.setRequestFactory(new HttpComponentsClientHttpRequestFactory(httpClient)); 52 | 53 | ObjectMapper objectMapper = new ObjectMapper(); 54 | objectMapper.registerModule(new Jackson2HalModule()); 55 | objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); 56 | objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); 57 | objectMapper.configure(DeserializationFeature.FAIL_ON_IGNORED_PROPERTIES, false); 58 | MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(); 59 | converter.setObjectMapper(objectMapper); 60 | restTemplate.getMessageConverters().add(0, converter); 61 | 62 | return restTemplate; 63 | 64 | } catch (KeyManagementException e) { 65 | // TODO Auto-generated catch block 66 | e.printStackTrace(); 67 | } catch (NoSuchAlgorithmException e) { 68 | // TODO Auto-generated catch block 69 | e.printStackTrace(); 70 | } catch (KeyStoreException e) { 71 | // TODO Auto-generated catch block 72 | e.printStackTrace(); 73 | } 74 | return null; 75 | } 76 | 77 | } 78 | -------------------------------------------------------------------------------- /microservices/frontend/src/main/java/microservices4vaadin/frontend/config/SerializableConfiguration.java: -------------------------------------------------------------------------------- 1 | package microservices4vaadin.frontend.config; 2 | 3 | import org.jdal.aop.SerializableProxyAdvisor; 4 | import org.jdal.aop.config.SerializableAnnotationBeanPostProcessor; 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.context.annotation.Configuration; 7 | import org.springframework.context.annotation.Scope; 8 | 9 | @Configuration 10 | public class SerializableConfiguration { 11 | 12 | @Bean 13 | public SerializableAnnotationBeanPostProcessor serializableAnnotationBeanPostProcessor() { 14 | return new SerializableAnnotationBeanPostProcessor(); 15 | } 16 | 17 | @Bean 18 | @Scope("prototype") 19 | public SerializableProxyAdvisor serializableProxyAdvisor() { 20 | return new SerializableProxyAdvisor(); 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /microservices/frontend/src/main/java/microservices4vaadin/frontend/config/SessionConfiguration.java: -------------------------------------------------------------------------------- 1 | package microservices4vaadin.frontend.config; 2 | 3 | import org.springframework.beans.factory.BeanFactory; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.beans.factory.support.DefaultListableBeanFactory; 6 | import org.springframework.context.ApplicationContext; 7 | import org.springframework.context.annotation.Bean; 8 | import org.springframework.context.annotation.Configuration; 9 | import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession; 10 | import org.springframework.session.web.http.CookieHttpSessionStrategy; 11 | import org.springframework.session.web.http.DefaultCookieSerializer; 12 | import org.springframework.session.web.http.HttpSessionStrategy; 13 | 14 | @Configuration 15 | @EnableRedisHttpSession 16 | public class SessionConfiguration { 17 | 18 | private final static String SESSION_SERIALIZATION_ID = "microservices4vaadin"; 19 | 20 | @Autowired 21 | private ApplicationContext appContext; 22 | 23 | @Bean 24 | public String overwriteSerializationId() { 25 | BeanFactory beanFactory = appContext.getAutowireCapableBeanFactory(); 26 | ((DefaultListableBeanFactory) beanFactory).setSerializationId(SESSION_SERIALIZATION_ID); 27 | return "overwritten"; 28 | } 29 | 30 | @Bean 31 | public HttpSessionStrategy httpSessionStrategy() { 32 | CookieHttpSessionStrategy cookieHttpSessionStrategy = new CookieHttpSessionStrategy(); 33 | DefaultCookieSerializer cookieSerializer = new DefaultCookieSerializer(); 34 | cookieSerializer.setCookieName("JSESSIONID"); 35 | cookieSerializer.setCookiePath("/"); 36 | cookieSerializer.setDomainNamePattern("^.+?\\.(\\w+\\.[a-z]+)$"); 37 | cookieHttpSessionStrategy.setCookieSerializer(cookieSerializer); 38 | return cookieHttpSessionStrategy; 39 | } 40 | 41 | @Bean 42 | public SessionSerializer springSessionDefaultRedisSerializer() { 43 | return new SessionSerializer(); 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /microservices/frontend/src/main/java/microservices4vaadin/frontend/config/SessionSerializer.java: -------------------------------------------------------------------------------- 1 | package microservices4vaadin.frontend.config; 2 | 3 | import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer; 4 | import org.springframework.data.redis.serializer.SerializationException; 5 | 6 | //@Slf4j 7 | public class SessionSerializer extends JdkSerializationRedisSerializer { 8 | 9 | @Override 10 | public Object deserialize(byte[] bytes) { 11 | try { 12 | Object obj = super.deserialize(bytes); 13 | return obj; 14 | } 15 | catch (SerializationException se) { 16 | // whenever inexistent classes from other service are deserialized they end up here 17 | //log.debug("Ignore: ", se.getRootCause()); 18 | } 19 | 20 | return null; 21 | } 22 | 23 | @Override 24 | public byte[] serialize(Object object) { 25 | return super.serialize(object); 26 | } 27 | 28 | } -------------------------------------------------------------------------------- /microservices/frontend/src/main/java/microservices4vaadin/frontend/rest/controller/AbstractRestController.java: -------------------------------------------------------------------------------- 1 | package microservices4vaadin.frontend.rest.controller; 2 | 3 | import javax.annotation.PostConstruct; 4 | 5 | import org.apache.http.client.HttpClient; 6 | import org.apache.http.impl.client.HttpClients; 7 | import org.springframework.hateoas.hal.Jackson2HalModule; 8 | import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; 9 | import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; 10 | import org.springframework.web.client.RestTemplate; 11 | 12 | import com.fasterxml.jackson.databind.DeserializationFeature; 13 | import com.fasterxml.jackson.databind.ObjectMapper; 14 | 15 | public abstract class AbstractRestController { 16 | 17 | private RestTemplate restTemplate; 18 | 19 | @PostConstruct 20 | public void init() { 21 | restTemplate = new RestTemplate(); 22 | HttpClient httpClient = HttpClients.createDefault(); 23 | restTemplate.setRequestFactory(new HttpComponentsClientHttpRequestFactory(httpClient)); 24 | 25 | ObjectMapper objectMapper = new ObjectMapper(); 26 | objectMapper.registerModule(new Jackson2HalModule()); 27 | objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); 28 | objectMapper.configure(DeserializationFeature.FAIL_ON_IGNORED_PROPERTIES, false); 29 | MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(); 30 | converter.setObjectMapper(objectMapper); 31 | restTemplate.getMessageConverters().add(0, converter); 32 | 33 | } 34 | 35 | public RestTemplate getRestTemplate() { 36 | return restTemplate; 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /microservices/frontend/src/main/java/microservices4vaadin/frontend/rest/controller/AcmeUserController.java: -------------------------------------------------------------------------------- 1 | package microservices4vaadin.frontend.rest.controller; 2 | 3 | import java.util.Arrays; 4 | 5 | import javax.servlet.http.Cookie; 6 | import javax.servlet.http.HttpServletRequest; 7 | 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.http.HttpEntity; 10 | import org.springframework.http.HttpHeaders; 11 | import org.springframework.http.HttpMethod; 12 | import org.springframework.stereotype.Controller; 13 | import org.springframework.web.client.RestOperations; 14 | 15 | import lombok.extern.slf4j.Slf4j; 16 | import microservices4vaadin.frontend.rest.resource.update.CredentialUpdateResource; 17 | 18 | @Controller 19 | @Slf4j 20 | public class AcmeUserController { 21 | 22 | public final static String USER_REST_URL = "/uaa/user"; 23 | 24 | @Autowired 25 | private RestOperations restTemplate; 26 | 27 | @Autowired 28 | private RestUtils restUtils; 29 | 30 | @Autowired 31 | private HttpServletRequest request; 32 | 33 | public static final String HEADER_AUTHORIZATION = "Authorization"; 34 | public static final String BEARER = "Bearer"; 35 | public static final String BASIC = "Basic"; 36 | 37 | public void updateCredentials(String email, String newPassword, String oldPassword) { 38 | log.debug("Setting up REST call to update user credentials"); 39 | CredentialUpdateResource resource = new CredentialUpdateResource(); 40 | resource.setEmail(email); 41 | resource.setNewPassword(newPassword); 42 | resource.setOldPassword(oldPassword); 43 | 44 | HttpHeaders headers = new HttpHeaders(); 45 | headers.put("COOKIE", Arrays.asList("JSESSIONID=" + getSessionId() + "; Path=/; HttpOnly")); 46 | 47 | HttpEntity entity = new HttpEntity<>(resource,headers); 48 | 49 | 50 | restTemplate.exchange(restUtils.getServiceUrl("authserver") + USER_REST_URL 51 | , HttpMethod.PATCH, entity, 52 | CredentialUpdateResource.class); 53 | } 54 | 55 | public String getSessionId() { 56 | 57 | Cookie[] cookies = request.getCookies(); 58 | 59 | for (Cookie c:cookies) 60 | { 61 | log.debug(String.format("Cookie: %s, %s, domain: %s",c.getName(), c.getValue(),c.getDomain())); 62 | if (c.getName().equals("JSESSIONID")) 63 | return c.getValue(); 64 | } 65 | return null; 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /microservices/frontend/src/main/java/microservices4vaadin/frontend/rest/controller/BookController.java: -------------------------------------------------------------------------------- 1 | package microservices4vaadin.frontend.rest.controller; 2 | 3 | import java.time.LocalDate; 4 | 5 | import org.springframework.stereotype.Controller; 6 | 7 | import microservices4vaadin.frontend.rest.resource.dto.Book; 8 | 9 | @Controller 10 | public class BookController extends AbstractRestController { 11 | public final static String TEST_CLASS_REST_URL = "/test"; 12 | 13 | // @Autowired 14 | // private RestUtils restUtils; 15 | 16 | // @HystrixCommand 17 | public Book findOne(Long testId) { 18 | Book book = new Book(); 19 | book.setName("My book of life"); 20 | book.setReleaseDate(LocalDate.now()); 21 | return book; 22 | // log.debug("Setting up REST call to get a bookingClass for itemId='{}'", bookingClassItemId.toString()); 23 | // 24 | // RequestEntity request = RequestEntity.get(URI.create(restUtils.getServiceUrl("backend") + BOOKING_CLASS_REST_URL + "/" + bookingClassItemId.toString())).accept(MediaTypes.HAL_JSON).build(); 25 | // ResponseEntity bookingClassResourceEntity = getRestTemplate().exchange(request, new ParameterizedTypeReference() {}); 26 | // 27 | // BookingClassResource bookingClassResource = bookingClassResourceEntity.getBody(); 28 | // BookingClassDTO bookingClassDTO = bookingClassResource.getContent(); 29 | // bookingClassDTO.setRelationalLinks(bookingClassResource.getLinks()); 30 | // return bookingClassDTO; 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /microservices/frontend/src/main/java/microservices4vaadin/frontend/rest/controller/RestUtils.java: -------------------------------------------------------------------------------- 1 | package microservices4vaadin.frontend.rest.controller; 2 | 3 | import java.net.URI; 4 | 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.cloud.client.ServiceInstance; 7 | import org.springframework.cloud.client.loadbalancer.LoadBalancerClient; 8 | import org.springframework.http.HttpStatus; 9 | import org.springframework.http.ResponseEntity; 10 | import org.springframework.stereotype.Component; 11 | 12 | import lombok.extern.slf4j.Slf4j; 13 | 14 | @Component 15 | @Slf4j 16 | public class RestUtils { 17 | 18 | @Autowired 19 | private LoadBalancerClient loadBalancer; 20 | 21 | /** 22 | * 23 | * @param serviceId 24 | * @return 25 | */ 26 | public URI getServiceUrl(String serviceId) { 27 | return getServiceUrl(serviceId, null); 28 | } 29 | 30 | /** 31 | * 32 | * @param serviceId 33 | * @param fallbackUri 34 | * @return 35 | */ 36 | protected URI getServiceUrl(String serviceId, String fallbackUri) { 37 | URI uri = null; 38 | try { 39 | ServiceInstance instance = loadBalancer.choose(serviceId); 40 | if (instance == null) { 41 | throw new RuntimeException("Can't find a service with serviceId = " + serviceId); 42 | } 43 | 44 | uri = instance.getUri(); 45 | log.debug("Resolved serviceId '{}' to URL '{} and secured '{}'.", serviceId, uri, instance.isSecure()); 46 | 47 | } catch (RuntimeException e) { 48 | // Eureka not available, use fallback if specified otherwise rethrow the error 49 | if (fallbackUri == null) { 50 | throw e; 51 | 52 | } else { 53 | uri = URI.create(fallbackUri); 54 | log.warn("Failed to resolve serviceId '{}'. Fallback to URL '{}'.", serviceId, uri); 55 | } 56 | } 57 | 58 | return uri; 59 | } 60 | 61 | public ResponseEntity createOkResponse(T body) { 62 | return createResponse(body, HttpStatus.OK); 63 | } 64 | 65 | public ResponseEntity createResponse(T body, HttpStatus httpStatus) { 66 | return new ResponseEntity<>(body, httpStatus); 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /microservices/frontend/src/main/java/microservices4vaadin/frontend/rest/resource/dto/AbstractHateoasEntity.java: -------------------------------------------------------------------------------- 1 | package microservices4vaadin.frontend.rest.resource.dto; 2 | 3 | import java.io.Serializable; 4 | import java.util.List; 5 | 6 | import lombok.Getter; 7 | import lombok.Setter; 8 | 9 | import org.springframework.hateoas.Link; 10 | 11 | import com.fasterxml.jackson.annotation.JsonIgnore; 12 | 13 | public abstract class AbstractHateoasEntity implements Serializable { 14 | 15 | private static final long serialVersionUID = 1307388647540531446L; 16 | 17 | @Getter 18 | @Setter 19 | @JsonIgnore 20 | private List relationalLinks; 21 | 22 | } 23 | -------------------------------------------------------------------------------- /microservices/frontend/src/main/java/microservices4vaadin/frontend/rest/resource/dto/AbstractPersonDTO.java: -------------------------------------------------------------------------------- 1 | package microservices4vaadin.frontend.rest.resource.dto; 2 | 3 | import javax.validation.constraints.NotNull; 4 | import javax.validation.constraints.Size; 5 | 6 | import lombok.EqualsAndHashCode; 7 | import lombok.Getter; 8 | import lombok.Setter; 9 | 10 | @Getter 11 | @Setter 12 | @EqualsAndHashCode(callSuper=false) 13 | public abstract class AbstractPersonDTO extends AbstractHateoasEntity { 14 | 15 | private static final long serialVersionUID = 860039839367963253L; 16 | 17 | public static enum Gender { 18 | MALE, 19 | FEMALE 20 | } 21 | 22 | private Long itemId; 23 | 24 | private Gender gender; 25 | 26 | @NotNull 27 | private String firstName; 28 | 29 | @NotNull 30 | private String lastName; 31 | 32 | private String title; 33 | 34 | private String phone; 35 | 36 | @NotNull 37 | @Size(min = 5, max = 255) 38 | private String email; 39 | 40 | } 41 | -------------------------------------------------------------------------------- /microservices/frontend/src/main/java/microservices4vaadin/frontend/rest/resource/dto/Book.java: -------------------------------------------------------------------------------- 1 | package microservices4vaadin.frontend.rest.resource.dto; 2 | 3 | import java.time.LocalDate; 4 | 5 | import lombok.Getter; 6 | import lombok.Setter; 7 | 8 | @Getter 9 | @Setter 10 | public class Book { 11 | 12 | private String name; 13 | private LocalDate releaseDate; 14 | 15 | } 16 | -------------------------------------------------------------------------------- /microservices/frontend/src/main/java/microservices4vaadin/frontend/rest/resource/dto/UserServiceUserDTO.java: -------------------------------------------------------------------------------- 1 | package microservices4vaadin.frontend.rest.resource.dto; 2 | 3 | import java.io.Serializable; 4 | import java.time.LocalDateTime; 5 | 6 | import javax.validation.constraints.NotNull; 7 | 8 | import com.fasterxml.jackson.annotation.JsonInclude; 9 | import com.fasterxml.jackson.annotation.JsonInclude.Include; 10 | 11 | import lombok.Getter; 12 | import lombok.Setter; 13 | import microservices4vaadin.auth.AcmeUser; 14 | import microservices4vaadin.frontend.rest.resource.dto.AbstractPersonDTO.Gender; 15 | 16 | @Getter 17 | @Setter 18 | public class UserServiceUserDTO implements Serializable { 19 | 20 | private static final long serialVersionUID = -7121116048753090277L; 21 | 22 | private Long itemId; 23 | 24 | @NotNull 25 | private String firstName; 26 | 27 | @NotNull 28 | private String lastName; 29 | 30 | private String title; 31 | 32 | private String phone; 33 | 34 | private Gender gender; 35 | 36 | private String lastModifiedBy; 37 | 38 | private LocalDateTime lastModifiedDateTime; 39 | 40 | @JsonInclude(Include.NON_NULL) 41 | private String language; 42 | 43 | private AcmeUser acmeUser; 44 | 45 | } 46 | -------------------------------------------------------------------------------- /microservices/frontend/src/main/java/microservices4vaadin/frontend/rest/resource/update/AbstractPersonUpdateResource.java: -------------------------------------------------------------------------------- 1 | package microservices4vaadin.frontend.rest.resource.update; 2 | 3 | import com.fasterxml.jackson.annotation.JsonInclude; 4 | import com.fasterxml.jackson.annotation.JsonInclude.Include; 5 | 6 | import lombok.Getter; 7 | import lombok.Setter; 8 | 9 | @Getter 10 | @Setter 11 | public abstract class AbstractPersonUpdateResource { 12 | 13 | @JsonInclude(Include.NON_NULL) 14 | private String gender; 15 | 16 | @JsonInclude(Include.NON_NULL) 17 | private String firstName; 18 | 19 | @JsonInclude(Include.NON_NULL) 20 | private String lastName; 21 | 22 | private String title; 23 | 24 | private String phone; 25 | 26 | @JsonInclude(Include.NON_NULL) 27 | private String email; 28 | 29 | } 30 | -------------------------------------------------------------------------------- /microservices/frontend/src/main/java/microservices4vaadin/frontend/rest/resource/update/AcmeUserUpdateResource.java: -------------------------------------------------------------------------------- 1 | package microservices4vaadin.frontend.rest.resource.update; 2 | 3 | import com.fasterxml.jackson.annotation.JsonInclude; 4 | import com.fasterxml.jackson.annotation.JsonInclude.Include; 5 | 6 | import lombok.Getter; 7 | import lombok.Setter; 8 | 9 | @Getter 10 | @Setter 11 | public class AcmeUserUpdateResource extends AbstractPersonUpdateResource { 12 | 13 | @JsonInclude(Include.NON_NULL) 14 | private String email; 15 | 16 | @JsonInclude(Include.NON_NULL) 17 | private String password; 18 | 19 | } 20 | -------------------------------------------------------------------------------- /microservices/frontend/src/main/java/microservices4vaadin/frontend/rest/resource/update/CredentialUpdateResource.java: -------------------------------------------------------------------------------- 1 | package microservices4vaadin.frontend.rest.resource.update; 2 | 3 | import com.fasterxml.jackson.annotation.JsonInclude; 4 | import com.fasterxml.jackson.annotation.JsonInclude.Include; 5 | 6 | import lombok.Getter; 7 | import lombok.Setter; 8 | 9 | @Getter 10 | @Setter 11 | public class CredentialUpdateResource { 12 | 13 | @JsonInclude(Include.NON_NULL) 14 | private String email; 15 | 16 | @JsonInclude(Include.NON_NULL) 17 | private String newPassword; 18 | 19 | @JsonInclude(Include.NON_NULL) 20 | private String oldPassword; 21 | 22 | } 23 | -------------------------------------------------------------------------------- /microservices/frontend/src/main/java/microservices4vaadin/frontend/rest/resource/update/UserServiceUserUpdateResource.java: -------------------------------------------------------------------------------- 1 | package microservices4vaadin.frontend.rest.resource.update; 2 | 3 | import java.time.LocalDateTime; 4 | 5 | import com.fasterxml.jackson.annotation.JsonInclude; 6 | import com.fasterxml.jackson.annotation.JsonInclude.Include; 7 | 8 | import lombok.Getter; 9 | import lombok.Setter; 10 | 11 | @Getter 12 | @Setter 13 | public class UserServiceUserUpdateResource { 14 | 15 | @JsonInclude(Include.NON_NULL) 16 | private String firstName; 17 | 18 | @JsonInclude(Include.NON_NULL) 19 | private String lastName; 20 | 21 | @JsonInclude(Include.NON_NULL) 22 | private String gender; 23 | 24 | @JsonInclude(Include.NON_EMPTY) 25 | private String title; 26 | 27 | @JsonInclude(Include.NON_NULL) 28 | private String lastModifiedBy; 29 | 30 | @JsonInclude(Include.NON_NULL) 31 | private LocalDateTime lastModifiedDateTime; 32 | 33 | @JsonInclude(Include.NON_NULL) 34 | private String language; 35 | 36 | } 37 | -------------------------------------------------------------------------------- /microservices/frontend/src/main/java/microservices4vaadin/frontend/ui/BookView.java: -------------------------------------------------------------------------------- 1 | package microservices4vaadin.frontend.ui; 2 | 3 | import javax.annotation.PostConstruct; 4 | 5 | import org.jdal.annotation.SerializableProxy; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | 8 | import com.vaadin.navigator.View; 9 | import com.vaadin.navigator.ViewChangeListener.ViewChangeEvent; 10 | import com.vaadin.server.Responsive; 11 | import com.vaadin.shared.ui.ContentMode; 12 | import com.vaadin.spring.annotation.SpringView; 13 | import com.vaadin.ui.Alignment; 14 | import com.vaadin.ui.Component; 15 | import com.vaadin.ui.HorizontalLayout; 16 | import com.vaadin.ui.Label; 17 | import com.vaadin.ui.Panel; 18 | import com.vaadin.ui.VerticalLayout; 19 | import com.vaadin.ui.themes.ValoTheme; 20 | 21 | import microservices4vaadin.frontend.rest.controller.BookController; 22 | import microservices4vaadin.frontend.rest.resource.dto.Book; 23 | 24 | @SpringView(name = BookView.VIEW_NAME) 25 | public class BookView extends Panel implements View { 26 | 27 | private static final long serialVersionUID = -7001285092564194997L; 28 | 29 | public static final String VIEW_NAME = "Book"; 30 | 31 | private boolean initialized = false; 32 | 33 | @Autowired 34 | @SerializableProxy 35 | private BookController bookController; 36 | 37 | private VerticalLayout layout; 38 | 39 | 40 | @PostConstruct 41 | void init() { 42 | 43 | layout = new VerticalLayout(); 44 | layout.setMargin(true); 45 | layout.setSpacing(true); 46 | 47 | setSizeFull(); 48 | } 49 | 50 | @Override 51 | public void enter(ViewChangeEvent event) { 52 | if (!initialized) { 53 | layout.addStyleName("dashboard-view"); 54 | 55 | layout.addComponent(buildHeader()); 56 | layout.addComponent(buildBody()); 57 | 58 | setContent(layout); 59 | Responsive.makeResponsive(layout); 60 | initialized = true; 61 | } 62 | } 63 | 64 | private Component buildHeader() { 65 | HorizontalLayout header = new HorizontalLayout(); 66 | header.addStyleName("viewheader"); 67 | header.setSpacing(true); 68 | 69 | Responsive.makeResponsive(header); 70 | 71 | Label title = new Label("Books"); 72 | title.setSizeFull(); 73 | title.addStyleName(ValoTheme.LABEL_H1); 74 | title.addStyleName(ValoTheme.LABEL_NO_MARGIN); 75 | header.addComponent(title); 76 | return header; 77 | } 78 | 79 | private Component buildBody() { 80 | VerticalLayout bodyLayout = new VerticalLayout(); 81 | bodyLayout.setSizeFull(); 82 | 83 | Book book = bookController.findOne(null); 84 | 85 | Label greetings = new Label("Book " + book.getName() 86 | + " found."); 87 | greetings.setContentMode(ContentMode.HTML); 88 | greetings.setWidth(null); 89 | 90 | bodyLayout.addComponent(greetings); 91 | bodyLayout.setComponentAlignment(greetings, Alignment.BOTTOM_CENTER); 92 | 93 | return bodyLayout; 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /microservices/frontend/src/main/java/microservices4vaadin/frontend/ui/MyMenuItemButton.java: -------------------------------------------------------------------------------- 1 | package microservices4vaadin.frontend.ui; 2 | 3 | import org.springframework.context.event.EventListener; 4 | 5 | import com.vaadin.ui.Button; 6 | import com.vaadin.ui.UI; 7 | 8 | import microservices4vaadin.frontend.ui.event.MyEvent.PostViewChangeEvent; 9 | 10 | public final class MyMenuItemButton extends Button { 11 | 12 | private static final long serialVersionUID = -318940943418526131L; 13 | 14 | private static final String STYLE_SELECTED = "selected"; 15 | 16 | private final MyViewType view; 17 | 18 | public MyMenuItemButton(final MyViewType view, final String label) { 19 | this.view = view; 20 | setPrimaryStyleName("valo-menu-item"); 21 | setIcon(view.getIcon()); 22 | setCaption(label); 23 | 24 | addClickListener(e -> UI.getCurrent().getNavigator().navigateTo(view.getViewName())); 25 | } 26 | 27 | @EventListener 28 | public void postViewChange(final PostViewChangeEvent event) { 29 | removeStyleName(STYLE_SELECTED); 30 | if (event.getView() == view) { 31 | addStyleName(STYLE_SELECTED); 32 | } 33 | } 34 | 35 | } -------------------------------------------------------------------------------- /microservices/frontend/src/main/java/microservices4vaadin/frontend/ui/MyNavigator.java: -------------------------------------------------------------------------------- 1 | package microservices4vaadin.frontend.ui; 2 | 3 | import org.springframework.context.ApplicationEventPublisher; 4 | 5 | import com.vaadin.navigator.Navigator; 6 | import com.vaadin.navigator.ViewChangeListener; 7 | import com.vaadin.spring.server.SpringVaadinServletService; 8 | import com.vaadin.ui.ComponentContainer; 9 | import com.vaadin.ui.UI; 10 | 11 | import microservices4vaadin.frontend.ui.event.MyEvent.BrowserResizeEvent; 12 | import microservices4vaadin.frontend.ui.event.MyEvent.CloseOpenWindowsEvent; 13 | import microservices4vaadin.frontend.ui.event.MyEvent.PostViewChangeEvent; 14 | 15 | public class MyNavigator extends Navigator { 16 | 17 | private static final long serialVersionUID = 3705219716729202395L; 18 | 19 | public MyNavigator(final ComponentContainer container) { 20 | super(UI.getCurrent(), container); 21 | 22 | initViewChangeListener(); 23 | 24 | } 25 | 26 | private void initViewChangeListener() { 27 | addViewChangeListener(new ViewChangeListener() { 28 | 29 | private static final long serialVersionUID = 4677058989845528128L; 30 | 31 | @Override 32 | public boolean beforeViewChange(final ViewChangeEvent event) { 33 | // Since there's no conditions in switching between the views 34 | // we can always return true. 35 | return true; 36 | } 37 | 38 | @Override 39 | public void afterViewChange(final ViewChangeEvent event) { 40 | MyViewType view = MyViewType.getByViewName(event 41 | .getViewName()); 42 | 43 | UI ui = UI.getCurrent(); 44 | 45 | ApplicationEventPublisher eventPublisher = (ApplicationEventPublisher) ((SpringVaadinServletService) ui.getSession().getService()).getWebApplicationContext(); 46 | // Appropriate events get fired after the view is changed. 47 | eventPublisher.publishEvent(new PostViewChangeEvent(MyVaadinUI.getCurrent(), view)); 48 | eventPublisher.publishEvent(new BrowserResizeEvent(MyVaadinUI.getCurrent())); 49 | eventPublisher.publishEvent(new CloseOpenWindowsEvent(MyVaadinUI.getCurrent())); 50 | } 51 | }); 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /microservices/frontend/src/main/java/microservices4vaadin/frontend/ui/MySessionInitListener.java: -------------------------------------------------------------------------------- 1 | package microservices4vaadin.frontend.ui; 2 | 3 | import org.jsoup.nodes.Element; 4 | 5 | import com.vaadin.server.BootstrapFragmentResponse; 6 | import com.vaadin.server.BootstrapListener; 7 | import com.vaadin.server.BootstrapPageResponse; 8 | import com.vaadin.server.ServiceException; 9 | import com.vaadin.server.SessionInitEvent; 10 | import com.vaadin.server.SessionInitListener; 11 | 12 | public class MySessionInitListener implements SessionInitListener { 13 | 14 | private static final long serialVersionUID = -6881763622904226924L; 15 | 16 | @Override 17 | public final void sessionInit(final SessionInitEvent event) 18 | throws ServiceException { 19 | 20 | event.getSession().addBootstrapListener(new BootstrapListener() { 21 | private static final long serialVersionUID = -4273381397632294262L; 22 | 23 | @Override 24 | public void modifyBootstrapPage(final BootstrapPageResponse response) { 25 | final Element head = response.getDocument().head(); 26 | head.appendElement("meta") 27 | .attr("name", "viewport") 28 | .attr("content", 29 | "width=device-width, initial-scale=1, maximum-scale=1.0, user-scalable=no"); 30 | head.appendElement("meta") 31 | .attr("name", "apple-mobile-web-app-capable") 32 | .attr("content", "yes"); 33 | head.appendElement("meta") 34 | .attr("name", "apple-mobile-web-app-status-bar-style") 35 | .attr("content", "black-translucent"); 36 | } 37 | 38 | @Override 39 | public void modifyBootstrapFragment( 40 | final BootstrapFragmentResponse response) { 41 | } 42 | }); 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /microservices/frontend/src/main/java/microservices4vaadin/frontend/ui/MyVaadinUIServlet.java: -------------------------------------------------------------------------------- 1 | package microservices4vaadin.frontend.ui; 2 | 3 | import javax.servlet.ServletException; 4 | 5 | import org.springframework.stereotype.Component; 6 | 7 | import com.vaadin.spring.server.SpringVaadinServlet; 8 | 9 | import lombok.extern.slf4j.Slf4j; 10 | 11 | @Component("vaadinServlet") 12 | @Slf4j 13 | public class MyVaadinUIServlet extends SpringVaadinServlet { 14 | 15 | private static final long serialVersionUID = 3407235182832472556L; 16 | 17 | @Override 18 | protected void servletInitialized() throws ServletException { 19 | super.servletInitialized(); 20 | getService().addSessionInitListener(new MySessionInitListener()); 21 | log.debug("MyVaadinUIServlet initialized"); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /microservices/frontend/src/main/java/microservices4vaadin/frontend/ui/MyViewType.java: -------------------------------------------------------------------------------- 1 | package microservices4vaadin.frontend.ui; 2 | 3 | import com.vaadin.icons.VaadinIcons; 4 | import com.vaadin.navigator.View; 5 | import com.vaadin.server.Resource; 6 | 7 | public enum MyViewType { 8 | HOME(HomeView.VIEW_NAME, "Home", HomeView.class, VaadinIcons.HOME, true) 9 | , BOOK(BookView.VIEW_NAME, "Book", BookView.class, VaadinIcons.BOOK, true); 10 | 11 | private final String viewName; 12 | private final String viewLabel; 13 | private final Class viewClass; 14 | private final Resource icon; 15 | private final boolean stateful; 16 | 17 | private MyViewType(final String viewName 18 | , final String viewLabel 19 | , final Class viewClass 20 | , final Resource icon 21 | , final boolean stateful) { 22 | this.viewName = viewName; 23 | this.viewLabel = viewLabel; 24 | this.viewClass = viewClass; 25 | this.icon = icon; 26 | this.stateful = stateful; 27 | } 28 | 29 | public boolean isStateful() { 30 | return stateful; 31 | } 32 | 33 | public String getViewName() { 34 | return viewName; 35 | } 36 | 37 | public String getViewLabel() { 38 | return viewLabel; 39 | } 40 | 41 | public Class getViewClass() { 42 | return viewClass; 43 | } 44 | 45 | public Resource getIcon() { 46 | return icon; 47 | } 48 | 49 | public static MyViewType getByViewName(final String viewName) { 50 | MyViewType result = null; 51 | for (MyViewType viewType : values()) { 52 | if (viewType.getViewName().equals(viewName)) { 53 | result = viewType; 54 | break; 55 | } 56 | } 57 | return result; 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /microservices/frontend/src/main/java/microservices4vaadin/frontend/ui/event/MyEvent.java: -------------------------------------------------------------------------------- 1 | package microservices4vaadin.frontend.ui.event; 2 | 3 | import org.springframework.context.ApplicationEvent; 4 | 5 | import microservices4vaadin.frontend.ui.MyViewType; 6 | 7 | 8 | public abstract class MyEvent { 9 | 10 | public static final class UserLoginRequestedEvent extends ApplicationEvent { 11 | 12 | private static final long serialVersionUID = -7321399321684894402L; 13 | 14 | private final String userName, password; 15 | 16 | public UserLoginRequestedEvent(final Object object, final String userName, 17 | final String password) { 18 | super(object); 19 | this.userName = userName; 20 | this.password = password; 21 | } 22 | 23 | public String getUserName() { 24 | return userName; 25 | } 26 | 27 | public String getPassword() { 28 | return password; 29 | } 30 | } 31 | 32 | public static class BrowserResizeEvent extends ApplicationEvent { 33 | private static final long serialVersionUID = -2271776614739128205L; 34 | 35 | public BrowserResizeEvent(Object source) { 36 | super(source); 37 | // TODO Auto-generated constructor stub 38 | } 39 | } 40 | 41 | public static class UserLoggedOutEvent extends ApplicationEvent { 42 | private static final long serialVersionUID = -4853914464587997188L; 43 | 44 | public UserLoggedOutEvent(Object source) { 45 | super(source); 46 | // TODO Auto-generated constructor stub 47 | } 48 | } 49 | 50 | // public static class NotificationsCountUpdatedEvent { 51 | // } 52 | 53 | 54 | public static final class PostViewChangeEvent extends ApplicationEvent { 55 | private static final long serialVersionUID = -3716302525487625973L; 56 | private final MyViewType view; 57 | 58 | public PostViewChangeEvent(final Object object, final MyViewType view) { 59 | super(object); 60 | this.view = view; 61 | } 62 | 63 | public MyViewType getView() { 64 | return view; 65 | } 66 | } 67 | 68 | public static class CloseOpenWindowsEvent extends ApplicationEvent { 69 | private static final long serialVersionUID = -4672026509699779702L; 70 | 71 | public CloseOpenWindowsEvent(Object source) { 72 | super(source); 73 | // TODO Auto-generated constructor stub 74 | } 75 | } 76 | 77 | public static class ProfileUpdatedEvent extends ApplicationEvent { 78 | private static final long serialVersionUID = 2215996354583273590L; 79 | 80 | public ProfileUpdatedEvent(Object source) { 81 | super(source); 82 | // TODO Auto-generated constructor stub 83 | } 84 | } 85 | 86 | } 87 | -------------------------------------------------------------------------------- /microservices/frontend/src/main/resources/VAADIN/themes/microservices4vaadin/images/profile-pic-300px.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khauser/microservices4vaadin/05aab5a8ee0484004bd3368184c617c2853c86be/microservices/frontend/src/main/resources/VAADIN/themes/microservices4vaadin/images/profile-pic-300px.jpg -------------------------------------------------------------------------------- /microservices/frontend/src/main/resources/VAADIN/themes/microservices4vaadin/microservices4vaadin.scss: -------------------------------------------------------------------------------- 1 | @import "../valo/valo"; 2 | 3 | @mixin microservices4vaadin { 4 | @include valo; 5 | 6 | } -------------------------------------------------------------------------------- /microservices/frontend/src/main/resources/VAADIN/themes/microservices4vaadin/styles.scss: -------------------------------------------------------------------------------- 1 | @import "microservices4vaadin"; 2 | @import "views/valo-menu-responsive"; 3 | 4 | // Main layout padding 5 | $view-padding: round($v-unit-size / 1.5) !default; 6 | 7 | .microservices4vaadin { 8 | @include microservices4vaadin; 9 | @include valo-menu-responsive; 10 | } -------------------------------------------------------------------------------- /microservices/frontend/src/main/resources/VAADIN/themes/microservices4vaadin/views/valo-menu-responsive.scss: -------------------------------------------------------------------------------- 1 | @mixin valo-menu-responsive() { 2 | .v-ui { 3 | 4 | @include width-range() { 5 | padding-top: $v-unit-size; 6 | -webkit-box-sizing: border-box; 7 | box-sizing: border-box; 8 | 9 | .v-loading-indicator { 10 | top: $v-unit-size; 11 | } 12 | 13 | > .v-widget { 14 | position: relative !important 15 | } 16 | 17 | .valo-menu { 18 | border-right: none; 19 | } 20 | 21 | .valo-menu-part { 22 | overflow: visible; 23 | } 24 | 25 | .valo-menu-toggle { 26 | display: inline-block; 27 | } 28 | 29 | .valo-menu-title { 30 | position: fixed; 31 | z-index: 100; 32 | top: 0; 33 | left: 0; 34 | right: 0; 35 | height: $v-unit-size !important; 36 | padding-top: 0; 37 | padding-bottom: 0; 38 | padding-left: 0; 39 | -webkit-backface-visibility: hidden; 40 | text-align: left; 41 | } 42 | 43 | .valo-menu-title .v-menubar-menuitem { 44 | font-size: 12px; 45 | white-space: nowrap; 46 | } 47 | 48 | .v-menubar-user-menu { 49 | position: fixed; 50 | z-index: 100; 51 | top: 0; 52 | right: 0; 53 | margin: 0; 54 | padding: 0; 55 | height: $v-unit-size; 56 | color: valo-font-color($v-selection-color, 0.5); 57 | max-width: 30%; 58 | -webkit-backface-visibility: hidden; 59 | 60 | .v-menubar-menuitem { 61 | line-height: $v-unit-size - 1px; 62 | white-space: nowrap; 63 | } 64 | 65 | .v-menubar-menuitem img.v-icon { 66 | display: inline-block; 67 | margin: 0 round($v-unit-size / 6) 0 0; 68 | width: round($v-unit-size / 2); 69 | height: round($v-unit-size / 2); 70 | border-radius: ceil($v-unit-size / 4); 71 | border: none; 72 | } 73 | } 74 | 75 | .valo-menuitems { 76 | @include valo-menu-style; 77 | position: fixed; 78 | z-index: 200; 79 | top: $v-unit-size; 80 | bottom: 0; 81 | height: auto; 82 | max-width: 100%; 83 | overflow: auto; 84 | padding: round($v-unit-size / 2) 0; 85 | @include transform(translatex(-100%)); 86 | @include transition(all 300ms); 87 | } 88 | 89 | .valo-menu-visible .valo-menuitems { 90 | @include transform(translatex(0%)); 91 | } 92 | } 93 | 94 | @include width-range($max: 500px) { 95 | .valo-menu-toggle .v-button-caption { 96 | display: none; 97 | } 98 | 99 | .v-menubar-user-menu .v-menubar-menuitem-caption { 100 | display: inline-block; 101 | width: round($v-unit-size / 2); 102 | overflow: hidden; 103 | } 104 | } 105 | } 106 | } -------------------------------------------------------------------------------- /microservices/frontend/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 8081 3 | contextPath: /ui 4 | use-forward-headers: true 5 | ssl: 6 | key-store: classpath:keystore.jks 7 | key-store-password: example 8 | key-password: example 9 | session: 10 | persistent: false 11 | 12 | vaadin: 13 | servlet: 14 | production-mode: false 15 | 16 | spring: 17 | redis: 18 | host: localhost 19 | port: 6379 20 | 21 | security: 22 | sessions: NEVER 23 | basic: 24 | enabled: false 25 | management: 26 | security: 27 | enabled: false 28 | 29 | eureka: 30 | client: 31 | serviceUrl: 32 | defaultZone: http://${eureka.host:localhost}:${eureka.port:8761}/eureka/ 33 | 34 | logging: 35 | level: 36 | microservices4vaadin: INFO 37 | org.springframework.security: INFO 38 | com.netflix.discovery: 'OFF' 39 | 40 | --- 41 | # For deployment in Docker containers 42 | spring: 43 | profiles: docker 44 | redis: 45 | host: redis 46 | -------------------------------------------------------------------------------- /microservices/frontend/src/main/resources/bootstrap.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: frontend 4 | cloud: 5 | config: 6 | uri: http://localhost:8888 7 | 8 | --- 9 | # For deployment in Docker containers 10 | spring: 11 | profiles: docker 12 | cloud: 13 | config: 14 | uri: http://192.168.59.103:8888 15 | -------------------------------------------------------------------------------- /microservices/frontend/src/main/resources/keystore.jks: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khauser/microservices4vaadin/05aab5a8ee0484004bd3368184c617c2853c86be/microservices/frontend/src/main/resources/keystore.jks -------------------------------------------------------------------------------- /microservices/frontend/src/main/webapp/META-INF/context.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /microservices/frontend/src/test/java/microservices4vaadin/frontend/VaadinApplicationTests.java: -------------------------------------------------------------------------------- 1 | package microservices4vaadin.frontend; 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 | @SpringBootTest 9 | @RunWith(SpringRunner.class) 10 | public class VaadinApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /microservices/hystrixdashboard/.gitignore: -------------------------------------------------------------------------------- 1 | .classpath 2 | .gradle/ 3 | .project 4 | .settings/ 5 | build/ 6 | /bin/ 7 | *.cache 8 | -------------------------------------------------------------------------------- /microservices/hystrixdashboard/build.gradle: -------------------------------------------------------------------------------- 1 | jar { 2 | baseName = 'hystrixdashboard' 3 | version = '0.0.1-SNAPSHOT' 4 | } 5 | ext { 6 | //docker 7 | imageName = dockerRepository + jar.baseName 8 | version = jar.version 9 | dockerBaseImage = 'anapsix/alpine-java:jre8' 10 | dockerExposePort = 7979 11 | } 12 | 13 | dependencies { 14 | compile("org.springframework.cloud:spring-cloud-starter-hystrix-dashboard") 15 | } 16 | -------------------------------------------------------------------------------- /microservices/hystrixdashboard/docker-entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | CONTAINER_IP='http://rancher-metadata.rancher.internal/latest/self/container/primary_ip' 4 | 5 | STATUS_CODE=$(curl --write-out %{http_code} --silent --output /dev/null ${CONTAINER_IP}) 6 | 7 | if [ "$STATUS_CODE" -eq "200" ] ; then 8 | EUREKA_INSTANCE_HOSTNAME=$(curl http://rancher-metadata.rancher.internal/latest/self/container/primary_ip) 9 | echo "Instance hostname: " . $EUREKA_INSTANCE_HOSTNAME 10 | exec java -jar -Djava.security.egd=file:/dev/./urandom -Dspring.profiles.active=docker -Deureka.instance.preferIpAddress=true -Deureka.instance.ipAddress=$EUREKA_INSTANCE_HOSTNAME -Deureka.instance.hostname=$EUREKA_INSTANCE_HOSTNAME /app.jar 11 | else 12 | exec java -jar -Djava.security.egd=file:/dev/./urandom -Dspring.profiles.active=docker /app.jar 13 | fi 14 | -------------------------------------------------------------------------------- /microservices/hystrixdashboard/src/main/java/microservices4vaadin/hystrixdashboard/HystrixDashboardApplication.java: -------------------------------------------------------------------------------- 1 | package microservices4vaadin.hystrixdashboard; 2 | 3 | import org.springframework.boot.autoconfigure.SpringBootApplication; 4 | import org.springframework.boot.builder.SpringApplicationBuilder; 5 | import org.springframework.boot.web.support.SpringBootServletInitializer; 6 | import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard; 7 | import org.springframework.stereotype.Controller; 8 | import org.springframework.web.bind.annotation.RequestMapping; 9 | 10 | @SpringBootApplication 11 | @Controller 12 | @EnableHystrixDashboard 13 | public class HystrixDashboardApplication extends SpringBootServletInitializer { 14 | 15 | @RequestMapping("/") 16 | public String home() { 17 | return "forward:/hystrix"; 18 | } 19 | 20 | @Override 21 | protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { 22 | return application.sources(HystrixDashboardApplication.class).web(true); 23 | } 24 | 25 | public static void main(String[] args) { 26 | new SpringApplicationBuilder(HystrixDashboardApplication.class).web(true).run(args); 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /microservices/hystrixdashboard/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | info: 2 | component: Hystrix Dashboard 3 | 4 | endpoints: 5 | restart: 6 | enabled: true 7 | shutdown: 8 | enabled: true 9 | 10 | server: 11 | port: 7979 12 | 13 | eureka: 14 | client: 15 | serviceUrl: 16 | defaultZone: http://${eureka.host:localhost}:${eureka.port:8761}/eureka/ 17 | 18 | logging: 19 | level: 20 | ROOT: INFO 21 | org.springframework.web: DEBUG 22 | com.netflix.discovery: 'OFF' 23 | 24 | --- 25 | # For deployment in Docker containers 26 | spring: 27 | profiles: docker 28 | -------------------------------------------------------------------------------- /microservices/hystrixdashboard/src/main/resources/bootstrap.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: hystrixdashboard 4 | cloud: 5 | config: 6 | uri: http://localhost:8888 7 | 8 | --- 9 | # For deployment in Docker containers 10 | spring: 11 | profiles: docker 12 | cloud: 13 | config: 14 | uri: http://192.168.59.103:8888 15 | -------------------------------------------------------------------------------- /microservices/hystrixdashboard/src/main/resources/log4j.properties: -------------------------------------------------------------------------------- 1 | log4j.rootLogger=INFO, FILE 2 | log4j.appender.FILE=org.apache.log4j.ConsoleAppender 3 | log4j.appender.FILE.layout=org.apache.log4j.PatternLayout 4 | log4j.appender.FILE.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %p %C:%L [%C{1}] [%M]: %m%n 5 | 6 | log4j.appender.FILE.httpclient=ERROR 7 | -------------------------------------------------------------------------------- /microservices/turbine/.gitignore: -------------------------------------------------------------------------------- 1 | .classpath 2 | .gradle/ 3 | .project 4 | .settings/ 5 | build/ 6 | /bin/ 7 | *.cache 8 | -------------------------------------------------------------------------------- /microservices/turbine/build.gradle: -------------------------------------------------------------------------------- 1 | jar { 2 | baseName = 'turbine' 3 | version = '0.0.1-SNAPSHOT' 4 | } 5 | ext { 6 | //docker 7 | imageName = dockerRepository + jar.baseName 8 | version = jar.version 9 | dockerBaseImage = 'anapsix/alpine-java:jre8' 10 | dockerExposePort = 8989 11 | } 12 | 13 | dependencies { 14 | compile("org.springframework.cloud:spring-cloud-netflix-turbine-amqp:1.0.3.RELEASE") 15 | } 16 | -------------------------------------------------------------------------------- /microservices/turbine/docker-entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | CONTAINER_IP='http://rancher-metadata.rancher.internal/latest/self/container/primary_ip' 4 | 5 | STATUS_CODE=$(curl --write-out %{http_code} --silent --output /dev/null ${CONTAINER_IP}) 6 | 7 | if [ "$STATUS_CODE" -eq "200" ] ; then 8 | EUREKA_INSTANCE_HOSTNAME=$(curl http://rancher-metadata.rancher.internal/latest/self/container/primary_ip) 9 | echo "Instance hostname: " . $EUREKA_INSTANCE_HOSTNAME 10 | exec java -jar -Djava.security.egd=file:/dev/./urandom -Dspring.profiles.active=docker -Deureka.instance.preferIpAddress=true -Deureka.instance.ipAddress=$EUREKA_INSTANCE_HOSTNAME -Deureka.instance.hostname=$EUREKA_INSTANCE_HOSTNAME /app.jar 11 | else 12 | exec java -jar -Djava.security.egd=file:/dev/./urandom -Dspring.profiles.active=docker /app.jar 13 | fi 14 | -------------------------------------------------------------------------------- /microservices/turbine/src/main/java/microservices4vaadin/turbine/TurbineApplication.java: -------------------------------------------------------------------------------- 1 | package microservices4vaadin.turbine; 2 | 3 | import org.springframework.boot.autoconfigure.SpringBootApplication; 4 | import org.springframework.boot.builder.SpringApplicationBuilder; 5 | import org.springframework.cloud.client.discovery.EnableDiscoveryClient; 6 | import org.springframework.cloud.netflix.turbine.amqp.EnableTurbineAmqp; 7 | 8 | @SpringBootApplication 9 | @EnableTurbineAmqp 10 | @EnableDiscoveryClient 11 | public class TurbineApplication { 12 | 13 | public static void main(String[] args) { 14 | new SpringApplicationBuilder(TurbineApplication.class).run(args); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /microservices/turbine/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | info: 2 | component: Turbine 3 | 4 | endpoints: 5 | restart: 6 | enabled: true 7 | shutdown: 8 | enabled: true 9 | 10 | server: 11 | port: 8989 12 | 13 | management: 14 | port: 8990 15 | 16 | eureka: 17 | client: 18 | serviceUrl: 19 | defaultZone: http://${eureka.host:localhost}:${eureka.port:8761}/eureka/ 20 | 21 | logging: 22 | level: 23 | root: INFO 24 | com.netflix.discovery: 'OFF' 25 | # org.springframework.integration: DEBUG 26 | 27 | --- 28 | # For deployment in Docker containers 29 | spring: 30 | profiles: docker 31 | -------------------------------------------------------------------------------- /microservices/turbine/src/main/resources/bootstrap.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: turbine 4 | cloud: 5 | config: 6 | uri: http://localhost:8888 7 | 8 | --- 9 | # For deployment in Docker containers 10 | spring: 11 | profiles: docker 12 | cloud: 13 | config: 14 | uri: http://192.168.59.103:8888 15 | -------------------------------------------------------------------------------- /microservices/userservice/.gitignore: -------------------------------------------------------------------------------- 1 | .classpath 2 | .gradle/ 3 | .project 4 | .settings/ 5 | build/ 6 | /bin/ 7 | *.cache 8 | /src/querydsl 9 | -------------------------------------------------------------------------------- /microservices/userservice/build.gradle: -------------------------------------------------------------------------------- 1 | jar { 2 | baseName = 'userservice' 3 | version = '0.0.1-SNAPSHOT' 4 | } 5 | 6 | ext { 7 | hsqlDbVersion = "2.4.0" 8 | dbUnitVersion = "2.5.4" 9 | flywayVersion = "4.0.3" 10 | springTestDbunitVersion = "1.3.0" 11 | 12 | //docker 13 | imageName = dockerRepository + jar.baseName 14 | version = jar.version 15 | dockerBaseImage = 'anapsix/alpine-java:jre8' 16 | } 17 | 18 | dependencyManagement { 19 | imports { 20 | mavenBom 'org.springframework.data:spring-data-releasetrain:Ingalls-SR8' 21 | } 22 | } 23 | 24 | dependencies { 25 | compile("org.springframework.boot:spring-boot-starter-web") { 26 | exclude module: 'spring-boot-starter-tomcat' 27 | } 28 | compile("org.springframework.boot:spring-boot-starter-data-rest") 29 | compile("org.springframework.boot:spring-boot-starter-hateoas") 30 | compile("org.springframework.boot:spring-boot-configuration-processor") 31 | 32 | compile("com.fasterxml.jackson.datatype:jackson-datatype-hibernate4:2.9.2") 33 | compile("com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.9.2") // used for LocalDate java8 34 | compile("org.jadira.usertype:usertype.extended:5.0.0.GA") // needed for dbunit and hibernate 35 | 36 | compile("org.springframework.boot:spring-boot-starter-data-jpa") 37 | runtime("mysql:mysql-connector-java") 38 | compile("org.flywaydb:flyway-core:${flywayVersion}"); 39 | 40 | compile project(':common') 41 | compile("org.axonframework:axon-amqp:2.4.3") 42 | compile("org.springframework.boot:spring-boot-starter-amqp:${springBootVersion}") 43 | 44 | testCompile("org.hsqldb:hsqldb:${hsqlDbVersion}") 45 | testRuntime("org.hsqldb:hsqldb:${hsqlDbVersion}") 46 | testCompile("org.dbunit:dbunit:${dbUnitVersion}") 47 | testCompile("com.github.springtestdbunit:spring-test-dbunit:${springTestDbunitVersion}") 48 | } 49 | -------------------------------------------------------------------------------- /microservices/userservice/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '2' 2 | 3 | services: 4 | rabbitmq: 5 | image: rabbitmq:3.5.1 6 | ports: 7 | - "15672:15672" 8 | - "5672:5672" 9 | -------------------------------------------------------------------------------- /microservices/userservice/docker-entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | CONTAINER_IP='http://rancher-metadata.rancher.internal/latest/self/container/primary_ip' 4 | 5 | STATUS_CODE=$(curl --write-out %{http_code} --silent --output /dev/null ${CONTAINER_IP}) 6 | 7 | if [ "$STATUS_CODE" -eq "200" ] ; then 8 | EUREKA_INSTANCE_HOSTNAME=$(curl http://rancher-metadata.rancher.internal/latest/self/container/primary_ip) 9 | echo "Instance hostname: " . $EUREKA_INSTANCE_HOSTNAME 10 | exec java -jar -Djava.security.egd=file:/dev/./urandom -Dspring.profiles.active=docker -Deureka.instance.preferIpAddress=true -Deureka.instance.ipAddress=$EUREKA_INSTANCE_HOSTNAME -Deureka.instance.hostname=$EUREKA_INSTANCE_HOSTNAME /app.jar 11 | else 12 | exec java -jar -Djava.security.egd=file:/dev/./urandom -Dspring.profiles.active=docker /app.jar 13 | fi 14 | -------------------------------------------------------------------------------- /microservices/userservice/src/main/java/microservices4vaadin/userservice/UserServiceApplication.java: -------------------------------------------------------------------------------- 1 | package microservices4vaadin.userservice; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | import org.springframework.boot.autoconfigure.SpringBootApplication; 6 | import org.springframework.boot.builder.SpringApplicationBuilder; 7 | import org.springframework.boot.web.support.SpringBootServletInitializer; 8 | import org.springframework.cloud.client.discovery.EnableDiscoveryClient; 9 | import org.springframework.context.annotation.Bean; 10 | import org.springframework.hateoas.UriTemplate; 11 | import org.springframework.hateoas.hal.CurieProvider; 12 | import org.springframework.hateoas.hal.DefaultCurieProvider; 13 | 14 | @SpringBootApplication 15 | @EnableDiscoveryClient 16 | public class UserServiceApplication extends SpringBootServletInitializer { 17 | 18 | private static final Logger LOG = LoggerFactory.getLogger(UserServiceApplication.class); 19 | 20 | public static String CURIE_NAMESPACE = "microservice4vaadin"; 21 | 22 | public @Bean CurieProvider curieProvider() { 23 | return new DefaultCurieProvider(CURIE_NAMESPACE, new UriTemplate("http://localhost:8082/profile/{rel}")); 24 | } 25 | 26 | public static void main(String[] args) { 27 | LOG.info("Starting AuthserverApplication"); 28 | new SpringApplicationBuilder(UserServiceApplication.class).run(args); 29 | } 30 | 31 | /** 32 | * Allows the application to be started when being deployed into a Servlet 3 container. 33 | * 34 | * @see org.springframework.boot.web.SpringBootServletInitializer#configure(org.springframework.boot.builder.SpringApplicationBuilder) 35 | */ 36 | @Override 37 | protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { 38 | return application.sources(UserServiceApplication.class); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /microservices/userservice/src/main/java/microservices4vaadin/userservice/configuration/CustomRepositoryConfiguration.java: -------------------------------------------------------------------------------- 1 | package microservices4vaadin.userservice.configuration; 2 | 3 | import org.springframework.context.annotation.Configuration; 4 | import org.springframework.data.jpa.repository.config.EnableJpaRepositories; 5 | import org.springframework.data.rest.core.config.RepositoryRestConfiguration; 6 | import org.springframework.data.rest.webmvc.config.RepositoryRestConfigurerAdapter; 7 | 8 | import microservices4vaadin.userservice.persistence.User; 9 | 10 | @Configuration 11 | @EnableJpaRepositories(basePackages={"microservices4vaadin.userservice.repository"}, repositoryImplementationPostfix = "CustomImpl") 12 | public class CustomRepositoryConfiguration extends RepositoryRestConfigurerAdapter { 13 | 14 | @Override 15 | public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) { 16 | config.exposeIdsFor(User.class); 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /microservices/userservice/src/main/java/microservices4vaadin/userservice/configuration/RabbitConfiguration.java: -------------------------------------------------------------------------------- 1 | package microservices4vaadin.userservice.configuration; 2 | 3 | import org.axonframework.contextsupport.spring.AnnotationDriven; 4 | import org.springframework.amqp.core.Binding; 5 | import org.springframework.amqp.core.FanoutExchange; 6 | import org.springframework.amqp.core.Queue; 7 | import org.springframework.amqp.rabbit.connection.CachingConnectionFactory; 8 | import org.springframework.amqp.rabbit.connection.ConnectionFactory; 9 | import org.springframework.amqp.rabbit.core.RabbitAdmin; 10 | import org.springframework.beans.factory.annotation.Required; 11 | import org.springframework.beans.factory.annotation.Value; 12 | import org.springframework.context.annotation.Bean; 13 | import org.springframework.context.annotation.Configuration; 14 | 15 | @Configuration 16 | @AnnotationDriven 17 | public class RabbitConfiguration { 18 | 19 | @Value("${spring.rabbitmq.hostname}") 20 | private String hostname; 21 | 22 | @Value("${spring.application.exchange}") 23 | private String exchangeName; 24 | 25 | @Value("${spring.application.queue}") 26 | private String queueName; 27 | 28 | @Value("${spring.application.index}") 29 | private Integer index; 30 | 31 | @Bean 32 | public String uniqueQueueName() { 33 | return queueName + "." + index; 34 | } 35 | 36 | @Bean 37 | Queue eventStream(String uniqueQueueName) { 38 | return new Queue(uniqueQueueName, false, false, true); 39 | } 40 | 41 | @Bean 42 | FanoutExchange eventBusExchange() { 43 | return new FanoutExchange(exchangeName, true, false); 44 | } 45 | 46 | @Bean 47 | Binding binding(String uniqueQueueName) { 48 | return new Binding(uniqueQueueName, Binding.DestinationType.QUEUE, exchangeName, "*.*", null); 49 | } 50 | 51 | @Bean 52 | ConnectionFactory connectionFactory() { 53 | CachingConnectionFactory connectionFactory = new CachingConnectionFactory(hostname); 54 | return connectionFactory; 55 | } 56 | 57 | @Bean 58 | @Required 59 | RabbitAdmin rabbitAdmin(String uniqueQueueName) { 60 | RabbitAdmin admin = new RabbitAdmin(connectionFactory()); 61 | admin.setAutoStartup(true); 62 | admin.declareExchange(eventBusExchange()); 63 | admin.declareQueue(eventStream(uniqueQueueName)); 64 | admin.declareBinding(binding(uniqueQueueName)); 65 | return admin; 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /microservices/userservice/src/main/java/microservices4vaadin/userservice/configuration/RestConfiguration.java: -------------------------------------------------------------------------------- 1 | package microservices4vaadin.userservice.configuration; 2 | 3 | import org.apache.http.client.HttpClient; 4 | import org.apache.http.impl.client.HttpClients; 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.context.annotation.Configuration; 7 | import org.springframework.data.projection.SpelAwareProxyProjectionFactory; 8 | import org.springframework.hateoas.hal.Jackson2HalModule; 9 | import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; 10 | import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; 11 | import org.springframework.web.client.RestTemplate; 12 | 13 | import com.fasterxml.jackson.databind.DeserializationFeature; 14 | import com.fasterxml.jackson.databind.ObjectMapper; 15 | import com.fasterxml.jackson.databind.SerializationFeature; 16 | import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; 17 | 18 | @Configuration 19 | public class RestConfiguration { 20 | 21 | @Bean 22 | public RestTemplate restTemplate() { 23 | RestTemplate restTemplate = new RestTemplate(); 24 | HttpClient httpClient = HttpClients.createDefault(); 25 | restTemplate.setRequestFactory(new HttpComponentsClientHttpRequestFactory(httpClient)); 26 | 27 | ObjectMapper objectMapper = new ObjectMapper(); 28 | objectMapper.registerModule(new Jackson2HalModule()); 29 | objectMapper.registerModule(new JavaTimeModule()); 30 | objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); 31 | objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); 32 | objectMapper.configure(DeserializationFeature.FAIL_ON_IGNORED_PROPERTIES, false); 33 | objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false); 34 | MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(); 35 | converter.setObjectMapper(objectMapper); 36 | restTemplate.getMessageConverters().add(0, converter); 37 | 38 | return restTemplate; 39 | } 40 | 41 | @Bean 42 | public SpelAwareProxyProjectionFactory projectionFactory() { 43 | return new SpelAwareProxyProjectionFactory(); 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /microservices/userservice/src/main/java/microservices4vaadin/userservice/handler/UserEventHandler.java: -------------------------------------------------------------------------------- 1 | package microservices4vaadin.userservice.handler; 2 | 3 | import org.axonframework.eventhandling.annotation.EventHandler; 4 | import org.axonframework.eventhandling.replay.ReplayAware; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.stereotype.Component; 7 | 8 | import lombok.extern.slf4j.Slf4j; 9 | import microservices4vaadin.userevents.UserCreatedEvent; 10 | import microservices4vaadin.userservice.persistence.User; 11 | import microservices4vaadin.userservice.repository.UserRepository; 12 | 13 | @Component 14 | @Slf4j 15 | public class UserEventHandler implements ReplayAware { 16 | 17 | @Autowired 18 | private UserRepository userRepository; 19 | 20 | @EventHandler 21 | public void handle(UserCreatedEvent event) { 22 | log.info("UserCreatedEvent: [{}] '{}'", event.getId(), event.getEmail()); 23 | User user = new User(); 24 | user.setItemId(event.getId()); 25 | user.setFirstName(event.getFirstName()); 26 | user.setLastName(event.getLastName()); 27 | user.setLanguage("en"); 28 | userRepository.save(user); 29 | } 30 | 31 | public void beforeReplay() { 32 | log.info("Event Replay is about to START. Clearing the View..."); 33 | } 34 | 35 | public void afterReplay() { 36 | log.info("Event Replay has FINISHED."); 37 | } 38 | 39 | public void onReplayFailed(Throwable cause) { 40 | log.error("Event Replay has FAILED."); 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /microservices/userservice/src/main/java/microservices4vaadin/userservice/handler/bootstrap.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: configserver 4 | -------------------------------------------------------------------------------- /microservices/userservice/src/main/java/microservices4vaadin/userservice/persistence/User.java: -------------------------------------------------------------------------------- 1 | package microservices4vaadin.userservice.persistence; 2 | 3 | import java.time.LocalDateTime; 4 | 5 | import javax.persistence.Column; 6 | import javax.persistence.Entity; 7 | import javax.persistence.Id; 8 | import javax.validation.constraints.Size; 9 | 10 | import org.hibernate.annotations.Type; 11 | import org.springframework.format.annotation.DateTimeFormat; 12 | 13 | import lombok.Getter; 14 | import lombok.Setter; 15 | 16 | @Entity 17 | @Getter 18 | @Setter 19 | public class User { 20 | 21 | public static enum Gender { 22 | MALE, 23 | FEMALE 24 | } 25 | 26 | @Id 27 | @Column(name = "id") 28 | private Long itemId; 29 | 30 | @Size(min = 0, max = 50) 31 | @Column(name = "first_name", length = 50) 32 | private String firstName; 33 | 34 | @Size(min = 0, max = 50) 35 | @Column(name = "last_name", length = 50) 36 | private String lastName; 37 | 38 | @Column(length = 50) 39 | private String lastModifiedBy; 40 | 41 | @Type(type = "org.jadira.usertype.dateandtime.threeten.PersistentLocalDateTime") 42 | @DateTimeFormat(pattern = "yyyy-MM-dd hh:mm:ss") 43 | private LocalDateTime lastModifiedDateTime; 44 | 45 | private Gender gender; 46 | 47 | private String title; 48 | 49 | private String phone; 50 | 51 | @Column(length = 5, nullable = false) 52 | private String language; 53 | 54 | } 55 | -------------------------------------------------------------------------------- /microservices/userservice/src/main/java/microservices4vaadin/userservice/repository/UserRepository.java: -------------------------------------------------------------------------------- 1 | package microservices4vaadin.userservice.repository; 2 | 3 | import org.springframework.data.jpa.repository.JpaRepository; 4 | import org.springframework.data.rest.core.annotation.RepositoryRestResource; 5 | 6 | import microservices4vaadin.userservice.persistence.User; 7 | 8 | @RepositoryRestResource(collectionResourceRel = "user", path = "user") 9 | public interface UserRepository extends JpaRepository { 10 | } 11 | -------------------------------------------------------------------------------- /microservices/userservice/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 0 3 | 4 | spring: 5 | application: 6 | name: userservice 7 | index: ${random.int[1024,4096]} 8 | exchange: user.events.fanout.exchange 9 | queue: event.stream 10 | terminal: user.axon.terminal 11 | rabbitmq: 12 | hostname: localhost 13 | profiles: 14 | active: ${profile:default} 15 | # DataSource settings: set here your own configurations for the database 16 | # connection. 17 | datasource: 18 | url: jdbc:mysql://localhost:3306/microservices4vaadin_userservicedb?useSSL=false&zeroDateTimeBehavior=convertToNull 19 | username: root 20 | password: 21 | driverClassName: com.mysql.jdbc.Driver 22 | testOnBorrow: true 23 | validationQuery: SELECT 1 24 | jpa: 25 | # Specify the DBMS 26 | database: MYSQL 27 | # Show or not log for each sql query 28 | show-sql: false 29 | hibernate: 30 | # Hibernate ddl auto (create, create-drop, update) 31 | ddl-auto: none 32 | # Naming strategy 33 | naming-strategy: org.hibernate.cfg.ImprovedNamingStrategy 34 | properties: 35 | hibernate: 36 | # Use spring.jpa.properties.* for Hibernate native properties (the prefix is 37 | # stripped before adding them to the entity manager) 38 | dialect: org.hibernate.dialect.MySQL5InnoDBDialect 39 | 40 | flyway: 41 | enabled: true 42 | baseline-on-migrate: true 43 | 44 | eureka: 45 | client: 46 | serviceUrl: 47 | defaultZone: http://${eureka.host:localhost}:${eureka.port:8761}/eureka/ 48 | 49 | logging: 50 | level: 51 | microservices4vaadin: INFO 52 | org.hibernate.SQL: INFO 53 | com.netflix.discovery: 'OFF' 54 | 55 | --- 56 | # For deployment in Docker containers 57 | spring: 58 | profiles: docker 59 | rabbitmq: 60 | hostname: rabbitmq 61 | datasource: 62 | url: jdbc:mysql://mysql/microservices4vaadin_userservicedb?useSSL=false&zeroDateTimeBehavior=convertToNull 63 | 64 | server: 65 | port: 7575 66 | -------------------------------------------------------------------------------- /microservices/userservice/src/main/resources/bootstrap.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: userservice 4 | cloud: 5 | config: 6 | uri: http://localhost:8888 7 | 8 | --- 9 | # For deployment in Docker containers 10 | spring: 11 | profiles: docker 12 | cloud: 13 | config: 14 | uri: http://192.168.59.103:8888 15 | -------------------------------------------------------------------------------- /microservices/userservice/src/main/resources/db/migration/Readme: -------------------------------------------------------------------------------- 1 | sql scripts for flywaydb -------------------------------------------------------------------------------- /microservices/userservice/src/main/resources/db/migration/V000001__init.sql: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khauser/microservices4vaadin/05aab5a8ee0484004bd3368184c617c2853c86be/microservices/userservice/src/main/resources/db/migration/V000001__init.sql -------------------------------------------------------------------------------- /microservices/userservice/src/main/resources/db/migration/V000002__remove_auto_incr.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE `user` CHANGE `id` `id` BIGINT(20) UNSIGNED NOT NULL; 2 | -------------------------------------------------------------------------------- /microservices/userservice/src/test/java/microservices4vaadin/userservice/rest/BasePersistenceTest.java: -------------------------------------------------------------------------------- 1 | package microservices4vaadin.userservice.rest; 2 | 3 | import java.sql.SQLException; 4 | 5 | import javax.annotation.PostConstruct; 6 | import javax.sql.DataSource; 7 | 8 | import org.dbunit.DatabaseTestCase; 9 | import org.dbunit.DatabaseUnitException; 10 | import org.dbunit.database.DatabaseConfig; 11 | import org.dbunit.database.DatabaseConnection; 12 | import org.dbunit.database.IDatabaseConnection; 13 | import org.dbunit.dataset.IDataSet; 14 | import org.dbunit.dataset.xml.FlatXmlDataSetBuilder; 15 | import org.dbunit.ext.hsqldb.HsqldbDataTypeFactory; 16 | import org.dbunit.operation.DatabaseOperation; 17 | import org.junit.runner.RunWith; 18 | import org.springframework.beans.factory.annotation.Autowired; 19 | import org.springframework.boot.test.context.SpringBootTest; 20 | import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; 21 | import org.springframework.test.context.ActiveProfiles; 22 | import org.springframework.test.context.junit4.SpringRunner; 23 | import org.springframework.transaction.annotation.EnableTransactionManagement; 24 | 25 | @SpringBootTest(webEnvironment=WebEnvironment.RANDOM_PORT) 26 | @RunWith(SpringRunner.class) 27 | @EnableTransactionManagement 28 | @ActiveProfiles("test") 29 | public abstract class BasePersistenceTest extends DatabaseTestCase { 30 | 31 | protected static final String DATASET = "microservices4vaadin_resource_test_dataset.xml"; 32 | 33 | @PostConstruct 34 | public void init() throws DatabaseUnitException, SQLException, Exception { 35 | DatabaseOperation.CLEAN_INSERT.execute(getConnection(), getDataSet()); 36 | } 37 | 38 | @Autowired 39 | private DataSource datasource; 40 | 41 | @Override 42 | protected IDatabaseConnection getConnection() throws Exception { 43 | DatabaseConnection connection = new DatabaseConnection(datasource.getConnection()); 44 | DatabaseConfig dbConfig = connection.getConfig(); 45 | dbConfig.setProperty(DatabaseConfig.PROPERTY_DATATYPE_FACTORY, new HsqldbDataTypeFactory()); 46 | return connection; 47 | } 48 | 49 | @Override 50 | protected IDataSet getDataSet() throws Exception { 51 | FlatXmlDataSetBuilder builder = new FlatXmlDataSetBuilder(); 52 | builder.setColumnSensing(true); 53 | return builder.build(this.getClass().getClassLoader().getResourceAsStream(DATASET)); 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /microservices/userservice/src/test/java/microservices4vaadin/userservice/rest/UserUpdateResource.java: -------------------------------------------------------------------------------- 1 | package microservices4vaadin.userservice.rest; 2 | 3 | import java.time.LocalDateTime; 4 | 5 | import com.fasterxml.jackson.annotation.JsonInclude; 6 | import com.fasterxml.jackson.annotation.JsonInclude.Include; 7 | 8 | import lombok.Getter; 9 | import lombok.Setter; 10 | 11 | @Getter 12 | @Setter 13 | public class UserUpdateResource { 14 | 15 | private Long itemId; 16 | 17 | @JsonInclude(Include.NON_NULL) 18 | private String firstName; 19 | 20 | @JsonInclude(Include.NON_NULL) 21 | private String lastName; 22 | 23 | @JsonInclude(Include.NON_NULL) 24 | private String createdBy; 25 | 26 | @JsonInclude(Include.NON_NULL) 27 | private LocalDateTime createdDateTime; 28 | 29 | @JsonInclude(Include.NON_NULL) 30 | private String lastModifiedBy; 31 | 32 | @JsonInclude(Include.NON_NULL) 33 | private LocalDateTime lastModifiedDateTime; 34 | 35 | @JsonInclude(Include.NON_NULL) 36 | private String language; 37 | 38 | } 39 | -------------------------------------------------------------------------------- /microservices/userservice/src/test/resources/application-test.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | datasource: 3 | url: jdbc:hsqldb:mem://microservices4vaadin_userservicetestdb?useSSL=false 4 | username: sa 5 | password: 6 | driverClassName: org.hsqldb.jdbcDriver 7 | validationQuery: SELECT 1 FROM INFORMATION_SCHEMA.SYSTEM_USERS 8 | jpa: 9 | generate-ddl: true 10 | show-sql: false 11 | hibernate: 12 | ddl-auto: create 13 | naming-strategy: org.hibernate.cfg.ImprovedNamingStrategy 14 | properties: 15 | hibernate: 16 | dialect: org.hibernate.dialect.HSQLDialect 17 | 18 | flyway: 19 | enabled: false 20 | -------------------------------------------------------------------------------- /microservices/userservice/src/test/resources/microservices4vaadin_empty_dataset.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /microservices/userservice/src/test/resources/microservices4vaadin_resource_test_dataset.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include "common", 2 | "microservices:config", 3 | "microservices:eventstore", 4 | "microservices:authserver", 5 | "microservices:discovery", 6 | "microservices:edge", 7 | "microservices:userservice", 8 | "microservices:frontend", 9 | "microservices:hystrixdashboard", 10 | "microservices:turbine" 11 | -------------------------------------------------------------------------------- /start-all.bat: -------------------------------------------------------------------------------- 1 | start cmd.exe /k "java -jar microservices/config/build/libs/config-0.0.1-SNAPSHOT.jar" 2 | timeout 30 3 | start cmd.exe /k "java -jar microservices/eventstore/build/libs/eventstore-0.0.1-SNAPSHOT.jar" 4 | start cmd.exe /k "java -jar microservices/authserver/build/libs/authserver-0.0.1-SNAPSHOT.jar" 5 | start cmd.exe /k "java -jar microservices/discovery/build/libs/discovery-0.0.1-SNAPSHOT.jar" 6 | start cmd.exe /k "java -jar microservices/edge/build/libs/edge-0.0.1-SNAPSHOT.jar" 7 | start cmd.exe /k "java -jar microservices/userservice/build/libs/userservice-0.0.1-SNAPSHOT.jar" 8 | start cmd.exe /k "java -jar microservices/frontend/build/libs/frontend-0.0.1-SNAPSHOT.jar" 9 | REM start cmd.exe /k "java -jar microservices/turbine/build/libs/turbine-0.0.1-SNAPSHOT.jar" 10 | REM start cmd.exe /k "java -jar microservices/hystrixdashboard/build/libs/hystrixdashboard-0.0.1-SNAPSHOT.jar" 11 | -------------------------------------------------------------------------------- /start-all.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | nohup java -jar microservices/config/build/libs/config-0.0.1-SNAPSHOT.jar > config.log & 4 | sleep 10 & wait %1 & 5 | nohup java -jar microservices/eventstore/build/libs/eventstore-0.0.1-SNAPSHOT.jar > eventstore.log & 6 | nohup java -jar microservices/discovery/build/libs/discovery-0.0.1-SNAPSHOT.jar > discovery.log & 7 | nohup java -jar microservices/authserver/build/libs/authserver-0.0.1-SNAPSHOT.jar > authserver.log & 8 | nohup java -jar microservices/edge/build/libs/edge-0.0.1-SNAPSHOT.jar > edge.log & 9 | nohup java -jar microservices/userservice/build/libs/userservice-0.0.1-SNAPSHOT.jar > userservice.log & 10 | nohup java -jar microservices/frontend/build/libs/frontend-0.0.1-SNAPSHOT.jar > frontend.log & 11 | #nohup java -jar microservices/hystrixdashboard/build/libs/hystrixdashboard-0.0.1-SNAPSHOT.jar > hystrixdashboard.log & 12 | #nohup java -jar microservices/turbine/build/libs/turbine-0.0.1-SNAPSHOT.jar > discovery.log & 13 | -------------------------------------------------------------------------------- /start-dockerBuild.bat: -------------------------------------------------------------------------------- 1 | start /D microservices\config %CD%\gradlew buildDockerImage 2 | start /D microservices\eventstore %CD%\gradlew buildDockerImage 3 | start /D microservices\discovery %CD%\gradlew buildDockerImage 4 | start /D microservices\authserver %CD%\gradlew buildDockerImage 5 | start /D microservices\edge %CD%\gradlew buildDockerImage 6 | start /D microservices\userservice %CD%\gradlew buildDockerImage 7 | start /D microservices\frontend %CD%\gradlew buildDockerImage 8 | #start /D microservices\turbine %CD%\gradlew buildDockerImage 9 | #start /D microservices\hystrixdashboard %CD%\gradlew buildDockerImage 10 | -------------------------------------------------------------------------------- /start-dockerBuild.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | SCRIPT=$(readlink -f "$0") 4 | # Absolute path this script is in, thus /home/user/bin 5 | SCRIPTPATH=$(dirname "$SCRIPT") 6 | #echo $SCRIPTPATH 7 | 8 | (cd microservices/config; $SCRIPTPATH/gradlew buildDockerContainer) 9 | (cd microservices/eventstore; $SCRIPTPATH/gradlew buildDockerContainer) 10 | (cd microservices/discovery; $SCRIPTPATH/gradlew buildDockerContainer) 11 | (cd microservices/authserver; $SCRIPTPATH/gradlew buildDockerContainer) 12 | (cd microservices/edge; $SCRIPTPATH/gradlew buildDockerContainer) 13 | (cd microservices/userservice; $SCRIPTPATH/gradlew buildDockerContainer) 14 | (cd microservices/frontend; $SCRIPTPATH/gradlew buildDockerContainer) 15 | #(cd microservices/hystrixdashboard; $SCRIPTPATH/gradlew buildDockerContainer) 16 | #(cd microservices/turbine; $SCRIPTPATH/gradlew buildDockerContainer) 17 | 18 | -------------------------------------------------------------------------------- /start-dockerPush.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | SCRIPT=$(readlink -f "$0") 4 | # Absolute path this script is in, thus /home/user/bin 5 | SCRIPTPATH=$(dirname "$SCRIPT") 6 | #echo $SCRIPTPATH 7 | 8 | (cd microservices/config; $SCRIPTPATH/gradlew pushDockerImage) 9 | (cd microservices/eventstore; $SCRIPTPATH/gradlew pushDockerImage) 10 | (cd microservices/authserver; $SCRIPTPATH/gradlew pushDockerImage) 11 | (cd microservices/discovery; $SCRIPTPATH/gradlew pushDockerImage) 12 | (cd microservices/edge; $SCRIPTPATH/gradlew pushDockerImage) 13 | (cd microservices/userservice; $SCRIPTPATH/gradlew pushDockerImage) 14 | (cd microservices/frontend; $SCRIPTPATH/gradlew pushDockerImage) 15 | --------------------------------------------------------------------------------