├── .gitignore ├── .idea ├── .gitignore └── finance-event-driven-elasticsearch-cloud-project.iml ├── BIST-Elastic-Model.txt ├── Finance-API.postman.json ├── LICENSE ├── README.md ├── img ├── depende.png ├── diagram.jpg ├── eureka.png ├── graf.png ├── kibana.png └── prom.png └── microservices └── microservices-demo ├── .gitignore ├── analytics-service ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── microservices │ │ │ └── demo │ │ │ └── analytics │ │ │ └── service │ │ │ ├── AnalyticsApplication.java │ │ │ ├── config │ │ │ ├── RedisConf.java │ │ │ └── WebSecurityConfig.java │ │ │ ├── controller │ │ │ └── AnalyticsController.java │ │ │ ├── converter │ │ │ ├── AvroToDbEntityModelTransformer.java │ │ │ └── EntityToResponseModelTransformer.java │ │ │ ├── entity │ │ │ ├── AnalyticsEntity.java │ │ │ └── base │ │ │ │ ├── AbstractAuditingEntity.java │ │ │ │ └── BaseEntity.java │ │ │ ├── model │ │ │ └── AnalyticsResponseModel.java │ │ │ ├── repository │ │ │ ├── AnalyticsCustomRepository.java │ │ │ ├── AnalyticsRepository.java │ │ │ └── impl │ │ │ │ └── AnalyticsRepositoryImpl.java │ │ │ ├── security │ │ │ ├── AnalyticsUser.java │ │ │ ├── AnalyticsUserDetailsService.java │ │ │ ├── AnalyticsUserJwtConverter.java │ │ │ └── AudienceValidator.java │ │ │ └── service │ │ │ ├── AnalyticsService.java │ │ │ └── impl │ │ │ ├── AnalyticsKafkaConsumer.java │ │ │ └── FinanceAnalyticsService.java │ └── resources │ │ ├── application.yml │ │ ├── banner.txt │ │ └── logback.xml │ └── test │ └── java │ └── com │ └── microservices │ └── demo │ └── analytics │ └── service │ └── AnalyticsApplicationTests.java ├── api-gateway ├── pom.xml └── src │ └── main │ ├── java │ └── com │ │ └── microservices │ │ └── demo │ │ └── api │ │ └── gateway │ │ ├── ApiGatewayApplication.java │ │ ├── config │ │ ├── GatewayConfig.java │ │ └── WebSecurityConfig.java │ │ ├── controller │ │ └── FallbackController.java │ │ └── model │ │ ├── AnalyticsDataFallbackModel.java │ │ └── QueryServiceFallbackModel.java │ └── resources │ ├── application.yml │ ├── banner.txt │ └── logback.xml ├── app-config-data ├── pom.xml └── src │ └── main │ ├── java │ └── com │ │ └── microservices │ │ └── demo │ │ └── config │ │ ├── AnalyticsServiceConfigData.java │ │ ├── ElasticConfigData.java │ │ ├── ElasticQueryConfigData.java │ │ ├── ElasticQueryServiceConfigData.java │ │ ├── ElasticQueryWebClientConfigData.java │ │ ├── FinanceDataStreamConfig.java │ │ ├── GatewayServiceConfigData.java │ │ ├── KafkaConfigData.java │ │ ├── KafkaConsumerConfigData.java │ │ ├── KafkaProducerConfigData.java │ │ ├── KafkaStreamsConfigData.java │ │ ├── KafkaStreamsServiceConfigData.java │ │ ├── RetryConfigData.java │ │ └── UserConfigData.java │ └── resources │ └── logback-common.xml ├── common-config ├── pom.xml └── src │ └── main │ └── java │ └── com │ └── microservices │ └── demo │ └── common │ └── config │ └── RetryConfig.java ├── common-util ├── pom.xml └── src │ └── main │ └── java │ └── com │ └── microservices │ └── demo │ └── common │ └── util │ └── CollectionsUtil.java ├── config-repository-files ├── config-client-analytics_service.yml ├── config-client-api_gateway.yml ├── config-client-elastic_query.yml ├── config-client-elastic_query_web.yml ├── config-client-finance_stream_service.yml ├── config-client-kafka_streams_service.yml ├── config-client-kafka_to_elastic.yml ├── config-client-reactive_elastic_query.yml ├── config-client-reactive_elastic_query_web.yml └── config-client.yml ├── config-server ├── pom.xml └── src │ └── main │ ├── java │ └── com │ │ └── microservices │ │ └── demo │ │ └── config │ │ └── server │ │ ├── ConfigServer.java │ │ └── config │ │ └── SecurityConfig.java │ └── resources │ ├── application.yml │ ├── banner.txt │ └── logback.xml ├── discovery-service ├── pom.xml └── src │ └── main │ ├── java │ └── com │ │ └── microservices │ │ └── demo │ │ └── discovery │ │ └── service │ │ └── DiscoveryClientApp.java │ └── resources │ ├── application-singleserver.yml │ ├── application.yml │ └── banner.txt ├── elastic-query-service-common ├── pom.xml └── src │ └── main │ └── java │ └── com │ └── microservices │ └── demo │ └── elastic │ └── query │ └── service │ └── common │ ├── api │ └── error │ │ └── handler │ │ └── ElasticQueryServiceHandler.java │ ├── converter │ └── ElasticToResponseModelConverter.java │ └── model │ ├── ElasticQueryRequestModel.java │ └── ElasticQueryResponseModel.java ├── elastic-query-service-reactive ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── microservices │ │ │ └── demo │ │ │ └── elastic │ │ │ └── query │ │ │ └── service │ │ │ └── reactive │ │ │ ├── ElasticQueryServiceReactiveApplication.java │ │ │ ├── config │ │ │ └── WebSecurityConfig.java │ │ │ ├── controller │ │ │ └── ElasticDocumentControllerReactive.java │ │ │ ├── repository │ │ │ └── ElasticQueryRepository.java │ │ │ └── service │ │ │ ├── ElasticQueryService.java │ │ │ ├── ReactiveElasticQueryClient.java │ │ │ └── impl │ │ │ ├── FinanceElasticQueryService.java │ │ │ └── FinanceReactiveElasticQueryClient.java │ └── resources │ │ ├── application.yml │ │ └── logback.xml │ └── test │ └── java │ └── com │ └── microservices │ └── demo │ └── elastic │ └── query │ └── service │ └── reactive │ └── ElasticQueryServiceReactiveApplicationTests.java ├── elastic-query-service ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── microservices │ │ │ └── demo │ │ │ └── elastic │ │ │ └── query │ │ │ └── service │ │ │ ├── ElasticQueryServiceApp.java │ │ │ ├── config │ │ │ ├── SecurityConfig.java │ │ │ └── WebClientConfig.java │ │ │ ├── controller │ │ │ └── ElasticDocumentController.java │ │ │ ├── converter │ │ │ └── UserPermissionToUserDetailConverter.java │ │ │ ├── dataaccess │ │ │ ├── entity │ │ │ │ └── UserPermission.java │ │ │ └── repository │ │ │ │ └── UserPermissionRepository.java │ │ │ ├── model │ │ │ ├── ElasticQueryServiceAnalyticsResponseModel.java │ │ │ ├── KafkaStreamsResponseModel.java │ │ │ └── assemblr │ │ │ │ └── ElasticQueryResponseModelAssembler.java │ │ │ ├── security │ │ │ ├── AudienceValidator.java │ │ │ ├── FinanceQueryUser.java │ │ │ ├── FinanceQueryUserDetailService.java │ │ │ ├── FinanceQueryUserJwtConverter.java │ │ │ ├── PermissionType.java │ │ │ └── QueryServicePermissionEvaluator.java │ │ │ ├── service │ │ │ ├── ElasticQueryService.java │ │ │ ├── QueryUserService.java │ │ │ └── impl │ │ │ │ ├── FinanceElasticQueryService.java │ │ │ │ └── FinanceQueryUserService.java │ │ │ └── util │ │ │ └── Constants.java │ └── resources │ │ ├── application.yml │ │ ├── banner.txt │ │ ├── init-data.sql │ │ ├── init-schema.sql │ │ └── logback.xml │ └── test │ └── java │ └── com │ └── microservices │ └── demo │ └── elastic │ └── query │ └── service │ └── ElasticQueryServiceAppTests.java ├── elastic-query-web-client-common ├── pom.xml └── src │ └── main │ └── java │ └── com │ └── microservices │ └── demo │ └── elastic │ └── query │ └── web │ └── client │ └── common │ ├── api │ └── handler │ │ └── ElasticQueryWebClientErrorHandler.java │ ├── exception │ └── ElasticQueryWebClientException.java │ └── model │ ├── ElasticQueryWebClientRequestModel.java │ └── ElasticQueryWebClientResponseModel.java ├── elastic-query-web-client-reactive ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── microservices │ │ │ └── demo │ │ │ └── reactive │ │ │ └── elastic │ │ │ └── query │ │ │ └── web │ │ │ └── client │ │ │ ├── ReactiveElasticQueryWebClientApplication.java │ │ │ ├── config │ │ │ ├── WebClientConfig.java │ │ │ └── WebSecurityConfig.java │ │ │ ├── controller │ │ │ └── QueryController.java │ │ │ └── service │ │ │ ├── ElasticQueryWebClient.java │ │ │ └── impl │ │ │ └── FinanceElasticQueryWebClient.java │ └── resources │ │ ├── application.yml │ │ ├── logback.xml │ │ └── templates │ │ ├── error.html │ │ ├── footer.html │ │ ├── header.html │ │ ├── home.html │ │ └── index.html │ └── test │ └── java │ └── com │ └── microservices │ └── demo │ └── reactive │ └── elastic │ └── query │ └── web │ └── client │ └── ReactiveElasticQueryWebClientApplicationTests.java ├── elastic-query-web-client ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── microservices │ │ │ └── demo │ │ │ └── elastic │ │ │ └── query │ │ │ └── web │ │ │ └── client │ │ │ ├── ElasticQueryWebClientApp.java │ │ │ ├── config │ │ │ ├── WebClientConfig.java │ │ │ └── WebSecurityConfig.java │ │ │ ├── controller │ │ │ └── QueryController.java │ │ │ ├── model │ │ │ ├── ElasticQueryWebClientAnalyticsResponseModel.java │ │ │ ├── LiveShareResponse.java │ │ │ └── LiveValuesResponse.java │ │ │ └── service │ │ │ ├── ElasticQueryWebClientService.java │ │ │ └── impl │ │ │ └── ElasticQueryWebClientServiceImpl.java │ └── resources │ │ ├── application.yml │ │ ├── banner.txt │ │ ├── logback.xml │ │ └── templates │ │ ├── error.html │ │ ├── footer.html │ │ ├── header.html │ │ ├── home.html │ │ └── index.html │ └── test │ └── java │ └── com │ └── microservices │ └── demo │ └── elastic │ └── query │ └── web │ └── client │ └── ElasticQueryWebClientAppTests.java ├── elastic ├── elastic-config │ ├── pom.xml │ └── src │ │ └── main │ │ └── java │ │ └── com │ │ └── microservices │ │ └── demo │ │ └── elastic │ │ └── config │ │ └── ElasticSearchConfig.java ├── elastic-index-client │ ├── pom.xml │ └── src │ │ └── main │ │ └── java │ │ └── com │ │ └── microservices │ │ └── demo │ │ └── elastic │ │ └── index │ │ └── client │ │ ├── repository │ │ └── FinanceElasticsearchIndexRepository.java │ │ ├── service │ │ ├── ElasticIndexClient.java │ │ └── impl │ │ │ ├── FinanceElasticIndexClient.java │ │ │ └── FinanceElasticRepositoryIndexClient.java │ │ └── util │ │ └── ElasticIndexUtil.java ├── elastic-model │ ├── pom.xml │ └── src │ │ └── main │ │ └── java │ │ └── com │ │ └── microservices │ │ └── demo │ │ └── elastic │ │ └── model │ │ └── index │ │ ├── IndexModel.java │ │ ├── impl │ │ └── FinanceIndexModel.java │ │ └── model │ │ └── FinanceAvroDTO.java ├── elastic-query-client │ ├── pom.xml │ └── src │ │ └── main │ │ └── java │ │ └── com │ │ └── microservices │ │ └── demo │ │ └── elastic │ │ └── query │ │ └── client │ │ ├── exception │ │ └── ElasticQueryClientException.java │ │ ├── repository │ │ └── FinanceElasticSearchQueryRepository.java │ │ ├── service │ │ ├── ElasticQueryClient.java │ │ └── impl │ │ │ ├── FinanceElasticQueryClient.java │ │ │ └── FinanceElasticRepositoryQueryClient.java │ │ └── util │ │ └── ElasticQueryUtil.java └── pom.xml ├── finance-stream-service ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── finance │ │ │ └── stream │ │ │ └── api │ │ │ ├── FinanceStreamApp.java │ │ │ ├── client │ │ │ └── FinanceService.java │ │ │ ├── converter │ │ │ └── FinanceToAvroConverter.java │ │ │ ├── dto │ │ │ └── FinanceApiDTO.java │ │ │ ├── init │ │ │ ├── StreamInitializer.java │ │ │ └── impl │ │ │ │ └── KafkaStreamInitializer.java │ │ │ ├── scheduler │ │ │ └── FinanceStreamScheduler.java │ │ │ └── service │ │ │ ├── ProcessData.java │ │ │ └── impl │ │ │ └── KafkaStreamProcessor.java │ └── resources │ │ ├── application.yml │ │ ├── banner.txt │ │ └── logback-spring.xml │ └── test │ ├── java │ └── com │ │ └── finance │ │ └── stream │ │ └── api │ │ ├── FinanceStreamAppTests.java │ │ └── MockSerdeConfig.java │ └── resources │ └── application-test.yml ├── infrastructure ├── docker-compose │ ├── .env │ ├── check-config-server-started.sh │ ├── check-keycloak-server-started.sh │ ├── common.yml │ ├── config │ │ ├── logback.conf │ │ └── prometheus.yml │ ├── elastic_cluster.yml │ ├── kafka_cluster.yml │ ├── keycloak.yml │ ├── monitoring.yml │ ├── redis_cluster.yml │ ├── services.yml │ ├── zipkin.yml │ └── zookeper.yml └── pom.xml ├── kafka-streams-service ├── pom.xml └── src │ └── main │ ├── java │ └── com │ │ └── microservices │ │ └── demo │ │ └── kafka │ │ └── streams │ │ └── service │ │ ├── Constants.java │ │ ├── KafkaStreamsServiceApplication.java │ │ ├── config │ │ ├── KafkaStreamsConfig.java │ │ └── WebSecurityConfig.java │ │ ├── controller │ │ └── KafkaStreamsController.java │ │ ├── init │ │ ├── StreamsInitializer.java │ │ └── impl │ │ │ └── KafkaStreamsInitializer.java │ │ ├── model │ │ └── KafkaStreamsResponseModel.java │ │ ├── runner │ │ ├── StreamsRunner.java │ │ └── impl │ │ │ └── KafkaStreamsRunner.java │ │ └── security │ │ ├── AudienceValidator.java │ │ ├── KafkaStreamsUser.java │ │ ├── KafkaStreamsUserDetailsService.java │ │ └── KafkaStreamsUserJwtConverter.java │ └── resources │ ├── application.yml │ ├── banner.txt │ └── logback.xml ├── kafka-to-elastic-service ├── pom.xml └── src │ └── main │ ├── java │ └── com │ │ └── microservices │ │ └── demo │ │ └── kafka │ │ └── to │ │ └── elastic │ │ └── service │ │ ├── KafkaToElasticServiceApp.java │ │ ├── consumer │ │ ├── KafkaConsumer.java │ │ └── impl │ │ │ └── FinanceKafkaConsumer.java │ │ └── converter │ │ └── AvroToElasticConverter.java │ └── resources │ ├── application.yml │ ├── banner.txt │ └── logback.xml ├── kafka ├── kafka-admin │ ├── pom.xml │ └── src │ │ └── main │ │ └── java │ │ └── com │ │ └── microservices │ │ └── demo │ │ └── kafka │ │ └── admin │ │ ├── client │ │ └── KafkaAdminClient.java │ │ ├── config │ │ ├── KafkaAdminConfig.java │ │ └── WebClientConfig.java │ │ └── exception │ │ └── KafkaClientException.java ├── kafka-consumer │ ├── pom.xml │ └── src │ │ └── main │ │ └── java │ │ └── com │ │ └── microservices │ │ └── demo │ │ └── kafka │ │ └── consumer │ │ └── config │ │ ├── KafkaConsumerConfig.java │ │ └── api │ │ └── KafkaConsumer.java ├── kafka-model │ ├── pom.xml │ └── src │ │ └── main │ │ ├── java │ │ └── com │ │ │ └── microservices │ │ │ └── demo │ │ │ └── kafka │ │ │ └── avro │ │ │ └── model │ │ │ ├── FinanceAnalyticsAvroModel.java │ │ │ ├── FinanceAvroModel.java │ │ │ └── Share.java │ │ └── resources │ │ └── avro │ │ ├── finance-analytics.avsc │ │ └── finance.avsc ├── kafka-producer │ ├── pom.xml │ └── src │ │ └── main │ │ └── java │ │ └── com │ │ └── microservices │ │ └── demo │ │ └── kafka │ │ └── producer │ │ └── config │ │ ├── KafkaProducerConfig.java │ │ └── service │ │ ├── KafkaProducer.java │ │ └── impl │ │ └── FinanceKafkaProducer.java └── pom.xml ├── mdc-interceptor ├── pom.xml └── src │ └── main │ └── java │ └── com │ └── microservices │ └── demo │ └── mdc │ ├── Constants.java │ ├── config │ ├── IdGeneratorConfig.java │ └── WebMvcConfig.java │ └── interceptor │ └── MDCHandlerInterceptor.java └── pom.xml /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled class file 2 | *.class 3 | 4 | # Log file 5 | *.log 6 | 7 | # BlueJ files 8 | *.ctxt 9 | 10 | # Mobile Tools for Java (J2ME) 11 | .mtj.tmp/ 12 | 13 | # Package Files # 14 | *.jar 15 | *.war 16 | *.nar 17 | *.ear 18 | *.zip 19 | *.tar.gz 20 | *.rar 21 | 22 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 23 | hs_err_pid* 24 | -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | # Editor-based HTTP Client requests 5 | /httpRequests/ 6 | # Datasource local storage ignored files 7 | /dataSources/ 8 | /dataSources.local.xml 9 | -------------------------------------------------------------------------------- /.idea/finance-event-driven-elasticsearch-cloud-project.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /BIST-Elastic-Model.txt: -------------------------------------------------------------------------------- 1 | { 2 | "mappings": { 3 | "properties": { 4 | "id": { 5 | "type": "text", 6 | "fields": { 7 | "keyword": { 8 | "type": "keyword", 9 | "ignore_above": 256 10 | } 11 | } 12 | }, 13 | "createdAt": { 14 | "type": "date", 15 | "format": "yyyy-MM-dd'T'HH:mm:ssZZ" 16 | }, 17 | "shareData": { 18 | "properties": { 19 | "dailyChangePercentage": { "type": "text" }, 20 | "dailyChange": { "type": "text" } 21 | "c": { "type": "text" }, 22 | "last": { "type": "text" } 23 | "dailyVolume": { "type": "text" } 24 | "previousDayClose": { "type": "text" } 25 | "description": { "type": "text" } 26 | } 27 | } 28 | } 29 | } 30 | } 31 | 32 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Ali CANLI 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /img/depende.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alicanli1995/finance-event-driven-elasticsearch-cloud-project/d116588824ac2b332c8ecbe19aeeefb94e6e1755/img/depende.png -------------------------------------------------------------------------------- /img/diagram.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alicanli1995/finance-event-driven-elasticsearch-cloud-project/d116588824ac2b332c8ecbe19aeeefb94e6e1755/img/diagram.jpg -------------------------------------------------------------------------------- /img/eureka.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alicanli1995/finance-event-driven-elasticsearch-cloud-project/d116588824ac2b332c8ecbe19aeeefb94e6e1755/img/eureka.png -------------------------------------------------------------------------------- /img/graf.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alicanli1995/finance-event-driven-elasticsearch-cloud-project/d116588824ac2b332c8ecbe19aeeefb94e6e1755/img/graf.png -------------------------------------------------------------------------------- /img/kibana.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alicanli1995/finance-event-driven-elasticsearch-cloud-project/d116588824ac2b332c8ecbe19aeeefb94e6e1755/img/kibana.png -------------------------------------------------------------------------------- /img/prom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alicanli1995/finance-event-driven-elasticsearch-cloud-project/d116588824ac2b332c8ecbe19aeeefb94e6e1755/img/prom.png -------------------------------------------------------------------------------- /microservices/microservices-demo/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/**/target/ 5 | !**/src/test/**/target/ 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | !**/src/main/**/build/ 30 | !**/src/test/**/build/ 31 | 32 | ### VS Code ### 33 | .vscode/ 34 | /.mvn/ 35 | /infrastructure/docker-compose/pgdata/ 36 | /infrastructure/docker-compose/volumes/ 37 | /infrastructure/docker-compose/pgdata/ 38 | /infrastructure/docker-compose/prometheus/ 39 | /infrastructure/docker-compose/logstash-logs/ 40 | -------------------------------------------------------------------------------- /microservices/microservices-demo/analytics-service/src/main/java/com/microservices/demo/analytics/service/AnalyticsApplication.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.analytics.service; 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.context.annotation.ComponentScan; 7 | import org.springframework.data.jpa.repository.config.EnableJpaAuditing; 8 | 9 | @EnableJpaAuditing 10 | @EnableDiscoveryClient 11 | @SpringBootApplication 12 | @ComponentScan(basePackages = {"com.microservices.demo"}) 13 | public class AnalyticsApplication { 14 | 15 | public static void main(String[] args) { 16 | SpringApplication.run(AnalyticsApplication.class, args); 17 | } 18 | } -------------------------------------------------------------------------------- /microservices/microservices-demo/analytics-service/src/main/java/com/microservices/demo/analytics/service/config/RedisConf.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.analytics.service.config; 2 | 3 | import org.springframework.cache.annotation.EnableCaching; 4 | import org.springframework.context.annotation.Bean; 5 | import org.springframework.context.annotation.Configuration; 6 | import org.springframework.data.redis.connection.RedisStandaloneConfiguration; 7 | import org.springframework.data.redis.connection.jedis.JedisConnectionFactory; 8 | import org.springframework.data.redis.core.RedisTemplate; 9 | 10 | @Configuration 11 | @EnableCaching 12 | public class RedisConf { 13 | 14 | @Bean 15 | public JedisConnectionFactory jedisConnectionFactory() { 16 | RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration("localhost", 6379); 17 | return new JedisConnectionFactory(redisStandaloneConfiguration); 18 | } 19 | 20 | @Bean 21 | public RedisTemplate redisTemplate() { 22 | RedisTemplate template = new RedisTemplate<>(); 23 | template.setConnectionFactory(jedisConnectionFactory()); 24 | return template; 25 | } 26 | 27 | } -------------------------------------------------------------------------------- /microservices/microservices-demo/analytics-service/src/main/java/com/microservices/demo/analytics/service/converter/AvroToDbEntityModelTransformer.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.analytics.service.converter; 2 | 3 | 4 | import com.microservices.demo.analytics.service.entity.AnalyticsEntity; 5 | import com.microservices.demo.kafka.avro.model.FinanceAnalyticsAvroModel; 6 | import lombok.RequiredArgsConstructor; 7 | import org.springframework.stereotype.Component; 8 | import org.springframework.util.IdGenerator; 9 | 10 | import java.util.List; 11 | 12 | @Component 13 | @RequiredArgsConstructor 14 | public class AvroToDbEntityModelTransformer { 15 | 16 | private final IdGenerator idGenerator; 17 | 18 | 19 | public List getEntityModel(List avroModels) { 20 | return avroModels.stream() 21 | .map(avroModel -> { 22 | var shareInformation = avroModel.getShareVolume().split(" "); 23 | return new AnalyticsEntity( 24 | idGenerator.generateId() 25 | , shareInformation[0].replaceAll(":", "") 26 | , shareInformation[1]); 27 | }) 28 | .peek(x -> x.setCreatedBy("SYSTEM")) 29 | .toList(); 30 | } 31 | 32 | 33 | } 34 | -------------------------------------------------------------------------------- /microservices/microservices-demo/analytics-service/src/main/java/com/microservices/demo/analytics/service/converter/EntityToResponseModelTransformer.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.analytics.service.converter; 2 | 3 | import com.microservices.demo.analytics.service.entity.AnalyticsEntity; 4 | import com.microservices.demo.analytics.service.model.AnalyticsResponseModel; 5 | import org.springframework.stereotype.Component; 6 | 7 | import java.util.List; 8 | import java.util.Optional; 9 | 10 | 11 | @Component 12 | public class EntityToResponseModelTransformer { 13 | 14 | public List getResponseModel(List analyticsEntity) { 15 | return Optional.ofNullable(analyticsEntity) 16 | .map(analyticsEntities -> analyticsEntities.stream() 17 | .map(this::getResponseModelSingle) 18 | .toList()) 19 | .orElse(List.of()); 20 | } 21 | 22 | public AnalyticsResponseModel getResponseModelSingle(AnalyticsEntity analyticsEntity) { 23 | return AnalyticsResponseModel.builder() 24 | .id(analyticsEntity.getId()) 25 | .shareName(analyticsEntity.getShareName()) 26 | .shareVolume(analyticsEntity.getShareVolume()) 27 | .recordTime(analyticsEntity.getCreatedDate()) 28 | .build(); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /microservices/microservices-demo/analytics-service/src/main/java/com/microservices/demo/analytics/service/entity/AnalyticsEntity.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.analytics.service.entity; 2 | 3 | import com.microservices.demo.analytics.service.entity.base.AbstractAuditingEntity; 4 | import com.microservices.demo.analytics.service.entity.base.BaseEntity; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Getter; 7 | import lombok.NoArgsConstructor; 8 | import lombok.Setter; 9 | 10 | import javax.persistence.Column; 11 | import javax.persistence.Entity; 12 | import javax.persistence.Id; 13 | import javax.persistence.Table; 14 | import javax.validation.constraints.NotNull; 15 | import java.util.Objects; 16 | import java.util.UUID; 17 | 18 | @Entity 19 | @Getter 20 | @Setter 21 | @NoArgsConstructor 22 | @AllArgsConstructor 23 | @Table(name = "finance_analytics") 24 | public class AnalyticsEntity extends AbstractAuditingEntity implements BaseEntity { 25 | 26 | @Id 27 | @NotNull 28 | @Column(name = "id", columnDefinition = "uuid") 29 | private UUID id; 30 | 31 | @NotNull 32 | @Column(name = "share_name") 33 | private String shareName; 34 | 35 | @NotNull 36 | @Column(name = "share_volume") 37 | private String shareVolume; 38 | 39 | @Override 40 | public boolean equals(Object o) { 41 | if (this == o) return true; 42 | if (o == null || getClass() != o.getClass()) return false; 43 | AnalyticsEntity that = (AnalyticsEntity) o; 44 | return Objects.equals(id, that.id); 45 | } 46 | 47 | @Override 48 | public int hashCode() { 49 | return Objects.hash(id); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /microservices/microservices-demo/analytics-service/src/main/java/com/microservices/demo/analytics/service/entity/base/BaseEntity.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.analytics.service.entity.base; 2 | 3 | public interface BaseEntity { 4 | PK getId(); 5 | } 6 | -------------------------------------------------------------------------------- /microservices/microservices-demo/analytics-service/src/main/java/com/microservices/demo/analytics/service/model/AnalyticsResponseModel.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.analytics.service.model; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | import java.io.Serializable; 9 | import java.time.Instant; 10 | import java.util.UUID; 11 | 12 | @Data 13 | @NoArgsConstructor 14 | @AllArgsConstructor 15 | @Builder 16 | public class AnalyticsResponseModel implements Serializable { 17 | private UUID id; 18 | private String shareName; 19 | private String shareVolume; 20 | private Instant recordTime; 21 | } 22 | -------------------------------------------------------------------------------- /microservices/microservices-demo/analytics-service/src/main/java/com/microservices/demo/analytics/service/repository/AnalyticsCustomRepository.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.analytics.service.repository; 2 | 3 | import java.util.Collection; 4 | 5 | public interface AnalyticsCustomRepository { 6 | 7 | PK persist(S entity); 8 | 9 | void batchPersist(Collection entities); 10 | 11 | S merge(S entity); 12 | 13 | void batchMerge(Collection entities); 14 | 15 | void clear(); 16 | } 17 | -------------------------------------------------------------------------------- /microservices/microservices-demo/analytics-service/src/main/java/com/microservices/demo/analytics/service/repository/AnalyticsRepository.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.analytics.service.repository; 2 | 3 | import com.microservices.demo.analytics.service.entity.AnalyticsEntity; 4 | import org.springframework.data.domain.Pageable; 5 | import org.springframework.data.jpa.repository.JpaRepository; 6 | import org.springframework.data.jpa.repository.Query; 7 | import org.springframework.data.repository.query.Param; 8 | 9 | import java.util.List; 10 | import java.util.UUID; 11 | 12 | public interface AnalyticsRepository extends JpaRepository,AnalyticsCustomRepository { 13 | 14 | @Query(value = "select e from AnalyticsEntity e where e.shareName=:shareName") 15 | List getAnalyticsEntitiesByShareNameAndOrderByCreatedDate(@Param("shareName") String shareName, Pageable pageable); 16 | } 17 | -------------------------------------------------------------------------------- /microservices/microservices-demo/analytics-service/src/main/java/com/microservices/demo/analytics/service/security/AnalyticsUser.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.analytics.service.security; 2 | 3 | 4 | import lombok.Builder; 5 | import lombok.Getter; 6 | import org.springframework.security.core.GrantedAuthority; 7 | import org.springframework.security.core.userdetails.UserDetails; 8 | 9 | import java.util.Collection; 10 | 11 | 12 | 13 | @Builder 14 | @Getter 15 | public class AnalyticsUser implements UserDetails { 16 | 17 | private String username; 18 | 19 | private Collection authorities; 20 | 21 | public void setAuthorities(Collection authorities) { 22 | this.authorities = authorities; 23 | } 24 | 25 | @Override 26 | public Collection getAuthorities() { 27 | return authorities; 28 | } 29 | 30 | @Override 31 | public String getPassword() { 32 | return "N/A"; 33 | } 34 | 35 | @Override 36 | public String getUsername() { 37 | return username; 38 | } 39 | 40 | @Override 41 | public boolean isAccountNonExpired() { 42 | return true; 43 | } 44 | 45 | @Override 46 | public boolean isAccountNonLocked() { 47 | return true; 48 | } 49 | 50 | @Override 51 | public boolean isCredentialsNonExpired() { 52 | return true; 53 | } 54 | 55 | @Override 56 | public boolean isEnabled() { 57 | return true; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /microservices/microservices-demo/analytics-service/src/main/java/com/microservices/demo/analytics/service/security/AnalyticsUserDetailsService.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.analytics.service.security; 2 | 3 | import org.springframework.security.core.userdetails.UserDetails; 4 | import org.springframework.security.core.userdetails.UserDetailsService; 5 | import org.springframework.security.core.userdetails.UsernameNotFoundException; 6 | import org.springframework.stereotype.Service; 7 | 8 | @Service 9 | public class AnalyticsUserDetailsService implements UserDetailsService { 10 | 11 | @Override 12 | public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { 13 | return AnalyticsUser.builder() 14 | .username(username) 15 | .build(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /microservices/microservices-demo/analytics-service/src/main/java/com/microservices/demo/analytics/service/security/AudienceValidator.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.analytics.service.security; 2 | 3 | 4 | import com.microservices.demo.config.AnalyticsServiceConfigData; 5 | import org.springframework.beans.factory.annotation.Qualifier; 6 | import org.springframework.security.oauth2.core.OAuth2Error; 7 | import org.springframework.security.oauth2.core.OAuth2TokenValidator; 8 | import org.springframework.security.oauth2.core.OAuth2TokenValidatorResult; 9 | import org.springframework.security.oauth2.jwt.Jwt; 10 | import org.springframework.stereotype.Component; 11 | 12 | 13 | @Qualifier(value = "analytics-service-audience-validator") 14 | @Component 15 | public class AudienceValidator implements OAuth2TokenValidator { 16 | 17 | private final AnalyticsServiceConfigData analyticsServiceConfigData; 18 | 19 | public AudienceValidator(AnalyticsServiceConfigData config) { 20 | analyticsServiceConfigData = config; 21 | } 22 | 23 | public OAuth2TokenValidatorResult validate(Jwt jwt) { 24 | if (jwt.getAudience().contains(analyticsServiceConfigData.getCustomAudience())) { 25 | return OAuth2TokenValidatorResult.success(); 26 | } else { 27 | OAuth2Error audienceError = 28 | new OAuth2Error("invalid_token", "The required audience " + 29 | analyticsServiceConfigData.getCustomAudience() + " is missing!", 30 | null); 31 | return OAuth2TokenValidatorResult.failure(audienceError); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /microservices/microservices-demo/analytics-service/src/main/java/com/microservices/demo/analytics/service/service/AnalyticsService.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.analytics.service.service; 2 | 3 | import com.microservices.demo.analytics.service.model.AnalyticsResponseModel; 4 | 5 | import java.util.List; 6 | 7 | 8 | public interface AnalyticsService { 9 | 10 | List getShareNameAnalytics(String shareName); 11 | 12 | AnalyticsResponseModel getShareLiveDataOnCache(String shareName); 13 | List getAllCacheData(); 14 | } 15 | 16 | -------------------------------------------------------------------------------- /microservices/microservices-demo/analytics-service/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: analytics-service 4 | profiles: 5 | active: analytics_service 6 | cloud: 7 | config: 8 | name: analytics-service,config-client 9 | uri: http://config-server:8888 10 | enabled: true 11 | username: spring_cloud_user 12 | password: spring_cloud_password 13 | config: 14 | import: configserver:http://config-server:8888 15 | 16 | eureka: 17 | client: 18 | serviceUrl: 19 | defaultZone: http://localhost:8761/eureka/ 20 | instance: 21 | lease-expiration-duration-in-seconds: 5 22 | lease-renewal-interval-in-seconds: 2 -------------------------------------------------------------------------------- /microservices/microservices-demo/analytics-service/src/main/resources/banner.txt: -------------------------------------------------------------------------------- 1 | _ _ _ ___ _ _ _ _ ___ 2 | /_\ | | (_) / __| /_\ | \| | | | |_ _| 3 | / _ \ | | | | | (__ / _ \ | .` | | |__ | | 4 | /_/ \_\ |_| |_| \___| /_/ \_\ |_|\_| |____| |___| 5 | 6 | ${application.title} ${application.version} 7 | Powered by Spring Boot ${spring-boot.version} -------------------------------------------------------------------------------- /microservices/microservices-demo/analytics-service/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /microservices/microservices-demo/analytics-service/src/test/java/com/microservices/demo/analytics/service/AnalyticsApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.analytics.service; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | public class AnalyticsApplicationTests { 8 | @Test 9 | public void contextLoads() { 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /microservices/microservices-demo/api-gateway/src/main/java/com/microservices/demo/api/gateway/ApiGatewayApplication.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.api.gateway; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.cloud.netflix.eureka.EnableEurekaClient; 6 | import org.springframework.context.annotation.ComponentScan; 7 | 8 | @EnableEurekaClient 9 | @SpringBootApplication 10 | @ComponentScan(basePackages = "com.microservices.demo") 11 | public class ApiGatewayApplication { 12 | public static void main(String[] args) { 13 | SpringApplication.run(ApiGatewayApplication.class, args); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /microservices/microservices-demo/api-gateway/src/main/java/com/microservices/demo/api/gateway/config/WebSecurityConfig.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.api.gateway.config; 2 | 3 | 4 | import org.springframework.context.annotation.Bean; 5 | import org.springframework.context.annotation.Configuration; 6 | import org.springframework.security.config.web.server.ServerHttpSecurity; 7 | import org.springframework.security.web.server.SecurityWebFilterChain; 8 | 9 | @Configuration 10 | public class WebSecurityConfig { 11 | 12 | @Bean 13 | public SecurityWebFilterChain webFluxSecurityConfig(ServerHttpSecurity httpSecurity) { 14 | httpSecurity.authorizeExchange() 15 | .anyExchange() 16 | .permitAll(); 17 | httpSecurity.csrf().disable(); 18 | return httpSecurity.build(); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /microservices/microservices-demo/api-gateway/src/main/java/com/microservices/demo/api/gateway/controller/FallbackController.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.api.gateway.controller; 2 | 3 | import com.microservices.demo.api.gateway.model.AnalyticsDataFallbackModel; 4 | import com.microservices.demo.api.gateway.model.QueryServiceFallbackModel; 5 | import lombok.extern.slf4j.Slf4j; 6 | import org.springframework.http.ResponseEntity; 7 | import org.springframework.web.bind.annotation.PostMapping; 8 | import org.springframework.web.bind.annotation.RequestMapping; 9 | import org.springframework.web.bind.annotation.RestController; 10 | 11 | @Slf4j 12 | @RestController 13 | @RequestMapping("/fallback") 14 | public class FallbackController { 15 | 16 | 17 | @PostMapping("/query-fallback") 18 | public ResponseEntity queryServiceFallback() { 19 | log.info("Returning fallback result for elastic-query-service!"); 20 | return ResponseEntity.ok(QueryServiceFallbackModel.builder() 21 | .fallbackMessage("Fallback result for elastic-query-service!") 22 | .build()); 23 | } 24 | 25 | @PostMapping("/analytics-fallback") 26 | public ResponseEntity analyticsServiceFallback() { 27 | log.info("Returning fallback result for analytics-service!"); 28 | return ResponseEntity.ok(AnalyticsDataFallbackModel.builder() 29 | .shareVolume("Non Data !") 30 | .build()); 31 | } 32 | 33 | 34 | @PostMapping("/streams-fallback") 35 | public ResponseEntity streamsServiceFallback() { 36 | log.info("Returning fallback result for kafka-streams-service!"); 37 | return ResponseEntity.ok(AnalyticsDataFallbackModel.builder() 38 | .shareVolume("Non Data !") 39 | .build()); 40 | } 41 | 42 | 43 | } 44 | -------------------------------------------------------------------------------- /microservices/microservices-demo/api-gateway/src/main/java/com/microservices/demo/api/gateway/model/AnalyticsDataFallbackModel.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.api.gateway.model; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | @Data 9 | @NoArgsConstructor 10 | @AllArgsConstructor 11 | @Builder 12 | public class AnalyticsDataFallbackModel { 13 | private String shareVolume; 14 | } 15 | -------------------------------------------------------------------------------- /microservices/microservices-demo/api-gateway/src/main/java/com/microservices/demo/api/gateway/model/QueryServiceFallbackModel.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.api.gateway.model; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | @Data 9 | @NoArgsConstructor 10 | @AllArgsConstructor 11 | @Builder 12 | public class QueryServiceFallbackModel { 13 | private String fallbackMessage; 14 | } 15 | -------------------------------------------------------------------------------- /microservices/microservices-demo/api-gateway/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: api-gateway 4 | profiles: 5 | active: api_gateway 6 | cloud: 7 | config: 8 | name: api-gateway,config-client 9 | uri: http://config-server:8888 10 | enabled: true 11 | username: spring_cloud_user 12 | password: spring_cloud_password 13 | config: 14 | import: configserver:http://config-server:8888 15 | 16 | eureka: 17 | client: 18 | serviceUrl: 19 | defaultZone: http://localhost:8761/eureka/ 20 | instance: 21 | lease-expiration-duration-in-seconds: 5 22 | lease-renewal-interval-in-seconds: 2 23 | 24 | -------------------------------------------------------------------------------- /microservices/microservices-demo/api-gateway/src/main/resources/banner.txt: -------------------------------------------------------------------------------- 1 | _ _ _ ___ _ _ _ _ ___ 2 | /_\ | | (_) / __| /_\ | \| | | | |_ _| 3 | / _ \ | | | | | (__ / _ \ | .` | | |__ | | 4 | /_/ \_\ |_| |_| \___| /_/ \_\ |_|\_| |____| |___| 5 | 6 | ${application.title} ${application.version} 7 | Powered by Spring Boot ${spring-boot.version} -------------------------------------------------------------------------------- /microservices/microservices-demo/api-gateway/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /microservices/microservices-demo/app-config-data/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | microservices-demo 7 | com.microservices.demo 8 | 0.0.1-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | 13 | app-config-data 14 | 15 | 16 | 17 | org.springframework.boot 18 | spring-boot 19 | 20 | 21 | org.projectlombok 22 | lombok 23 | provided 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /microservices/microservices-demo/app-config-data/src/main/java/com/microservices/demo/config/AnalyticsServiceConfigData.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.config; 2 | 3 | import lombok.Data; 4 | import org.springframework.boot.context.properties.ConfigurationProperties; 5 | import org.springframework.context.annotation.Configuration; 6 | 7 | @Data 8 | @Configuration 9 | @ConfigurationProperties(prefix = "analytics-service") 10 | public class AnalyticsServiceConfigData { 11 | private String version; 12 | private String customAudience; 13 | } 14 | 15 | -------------------------------------------------------------------------------- /microservices/microservices-demo/app-config-data/src/main/java/com/microservices/demo/config/ElasticConfigData.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.config; 2 | 3 | import lombok.Data; 4 | import org.springframework.boot.context.properties.ConfigurationProperties; 5 | import org.springframework.context.annotation.Configuration; 6 | 7 | @Data 8 | @Configuration 9 | @ConfigurationProperties(prefix = "elastic-config") 10 | public class ElasticConfigData { 11 | private String indexName; 12 | private String connectionUrl; 13 | private int connectionTimeout; 14 | private int socketTimeout; 15 | } 16 | -------------------------------------------------------------------------------- /microservices/microservices-demo/app-config-data/src/main/java/com/microservices/demo/config/ElasticQueryConfigData.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.config; 2 | 3 | import lombok.Data; 4 | import org.springframework.boot.context.properties.ConfigurationProperties; 5 | import org.springframework.context.annotation.Configuration; 6 | 7 | @Data 8 | @Configuration 9 | @ConfigurationProperties(prefix = "elastic-query-config") 10 | public class ElasticQueryConfigData { 11 | private String shareData; 12 | } 13 | -------------------------------------------------------------------------------- /microservices/microservices-demo/app-config-data/src/main/java/com/microservices/demo/config/ElasticQueryServiceConfigData.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.config; 2 | 3 | import lombok.Data; 4 | import org.springframework.boot.context.properties.ConfigurationProperties; 5 | import org.springframework.context.annotation.Configuration; 6 | 7 | @Data 8 | @Configuration 9 | @ConfigurationProperties(prefix = "elastic-query-service") 10 | public class ElasticQueryServiceConfigData { 11 | private String version; 12 | private String customAudience; 13 | private Long backPressureDelayMs; 14 | private WebClient webClient; 15 | private Query queryFromKafkaStateStore; 16 | private Query queryFromAnalyticsDatabase; 17 | 18 | @Data 19 | public static class WebClient { 20 | private Integer connectTimeoutMs; 21 | private Integer readTimeoutMs; 22 | private Integer writeTimeoutMs; 23 | private Integer maxInMemorySize; 24 | private String contentType; 25 | private String acceptType; 26 | private String queryType; 27 | } 28 | 29 | @Data 30 | public static class Query { 31 | private String method; 32 | private String accept; 33 | private String uri; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /microservices/microservices-demo/app-config-data/src/main/java/com/microservices/demo/config/ElasticQueryWebClientConfigData.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.config; 2 | 3 | import lombok.Data; 4 | import org.springframework.boot.context.properties.ConfigurationProperties; 5 | import org.springframework.context.annotation.Configuration; 6 | 7 | import java.util.List; 8 | 9 | @Data 10 | @Configuration 11 | @ConfigurationProperties(prefix = "elastic-query-web-client") 12 | public class ElasticQueryWebClientConfigData { 13 | 14 | private WebClient webClient; 15 | private Query queryByText; 16 | 17 | @Data 18 | public static class WebClient { 19 | private Integer connectTimeoutMs; 20 | private Integer readTimeoutMs; 21 | private Integer writeTimeoutMs; 22 | private Integer maxInMemorySize; 23 | private String contentType; 24 | private String acceptType; 25 | private String baseUrl; 26 | private String serviceId; 27 | private List instances; 28 | } 29 | 30 | 31 | @Data 32 | public static class Query { 33 | private String method; 34 | private String accept; 35 | private String uri; 36 | } 37 | 38 | @Data 39 | public static class Instance { 40 | private String id; 41 | private String host; 42 | private Integer port; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /microservices/microservices-demo/app-config-data/src/main/java/com/microservices/demo/config/FinanceDataStreamConfig.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.config; 2 | 3 | import lombok.Data; 4 | import org.springframework.boot.context.properties.ConfigurationProperties; 5 | import org.springframework.context.annotation.Configuration; 6 | 7 | import java.util.List; 8 | 9 | @Data 10 | @Configuration 11 | @ConfigurationProperties(prefix = "finance-share") 12 | public class FinanceDataStreamConfig { 13 | private List shareList; 14 | private String urlAppend; 15 | } 16 | -------------------------------------------------------------------------------- /microservices/microservices-demo/app-config-data/src/main/java/com/microservices/demo/config/GatewayServiceConfigData.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.config; 2 | 3 | 4 | import lombok.Data; 5 | import org.springframework.boot.context.properties.ConfigurationProperties; 6 | import org.springframework.context.annotation.Configuration; 7 | 8 | @Data 9 | @Configuration 10 | @ConfigurationProperties(prefix = "gateway-service") 11 | public class GatewayServiceConfigData { 12 | private Long timeoutMs; 13 | private Float failureRateThreshold; 14 | private Float slowCallRateThreshold; 15 | private Long slowCallDurationThreshold; 16 | private Integer permittedNumOfCallsInHalfOpenState; 17 | private Integer slidingWindowSize; 18 | private Integer minNumberOfCalls; 19 | private Long waitDurationInOpenState; 20 | 21 | } 22 | 23 | -------------------------------------------------------------------------------- /microservices/microservices-demo/app-config-data/src/main/java/com/microservices/demo/config/KafkaConfigData.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.config; 2 | 3 | import lombok.Data; 4 | import org.springframework.boot.context.properties.ConfigurationProperties; 5 | import org.springframework.context.annotation.Configuration; 6 | 7 | import java.util.List; 8 | 9 | @Data 10 | @Configuration 11 | @ConfigurationProperties(prefix = "kafka-config") 12 | public class KafkaConfigData { 13 | private String bootstrapServers; 14 | private String schemaRegistryUrlKey; 15 | private String schemaRegistryUrl; 16 | private String topicName; 17 | private List topicNamesToCreate; 18 | private Integer numOfPartitions; 19 | private Short replicationFactor; 20 | } 21 | -------------------------------------------------------------------------------- /microservices/microservices-demo/app-config-data/src/main/java/com/microservices/demo/config/KafkaConsumerConfigData.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.config; 2 | 3 | 4 | import lombok.Data; 5 | import org.springframework.boot.context.properties.ConfigurationProperties; 6 | import org.springframework.context.annotation.Configuration; 7 | 8 | @Data 9 | @Configuration 10 | @ConfigurationProperties(prefix = "kafka-consumer-config") 11 | public class KafkaConsumerConfigData { 12 | private String keyDeserializer; 13 | private String valueDeserializer; 14 | private String consumerGroupId; 15 | private String autoOffsetReset; 16 | private String specificAvroReaderKey; 17 | private String specificAvroReader; 18 | private Boolean batchListener; 19 | private Boolean autoStartup; 20 | private Integer concurrencyLevel; 21 | private Integer sessionTimeoutMs; 22 | private Integer heartbeatIntervalMs; 23 | private Integer maxPollIntervalMs; 24 | private Integer maxPollRecords; 25 | private Integer maxPartitionFetchBytesDefault; 26 | private Integer maxPartitionFetchBytesBoostFactor; 27 | private Long pollTimeoutMs; 28 | } 29 | -------------------------------------------------------------------------------- /microservices/microservices-demo/app-config-data/src/main/java/com/microservices/demo/config/KafkaProducerConfigData.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.config; 2 | 3 | import lombok.Data; 4 | import org.springframework.boot.context.properties.ConfigurationProperties; 5 | import org.springframework.context.annotation.Configuration; 6 | 7 | @Data 8 | @Configuration 9 | @ConfigurationProperties(prefix = "kafka-producer-config") 10 | public class KafkaProducerConfigData { 11 | private String keySerializerClass; 12 | private String valueSerializerClass; 13 | private String compressionType; 14 | private String acks; 15 | private Integer batchSize; 16 | private Integer batchSizeBoostFactor; 17 | private Integer lingerMs; 18 | private Integer requestTimeoutMs; 19 | private Integer retryCount; 20 | } 21 | -------------------------------------------------------------------------------- /microservices/microservices-demo/app-config-data/src/main/java/com/microservices/demo/config/KafkaStreamsConfigData.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.config; 2 | 3 | import lombok.Data; 4 | import org.springframework.boot.context.properties.ConfigurationProperties; 5 | import org.springframework.context.annotation.Configuration; 6 | 7 | @Data 8 | @Configuration 9 | @ConfigurationProperties(prefix = "kafka-streams-config") 10 | public class KafkaStreamsConfigData { 11 | private String applicationID; 12 | private String inputTopicName; 13 | private String outputTopicName; 14 | private String stateFileLocation; 15 | private String wordCountStoreName; 16 | } 17 | -------------------------------------------------------------------------------- /microservices/microservices-demo/app-config-data/src/main/java/com/microservices/demo/config/KafkaStreamsServiceConfigData.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.config; 2 | 3 | import lombok.Data; 4 | import org.springframework.boot.context.properties.ConfigurationProperties; 5 | import org.springframework.context.annotation.Configuration; 6 | 7 | @Data 8 | @Configuration 9 | @ConfigurationProperties(prefix = "kafka-streams-service") 10 | public class KafkaStreamsServiceConfigData { 11 | private String version; 12 | private String customAudience; 13 | } 14 | -------------------------------------------------------------------------------- /microservices/microservices-demo/app-config-data/src/main/java/com/microservices/demo/config/RetryConfigData.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.config; 2 | 3 | import lombok.Data; 4 | import org.springframework.boot.context.properties.ConfigurationProperties; 5 | import org.springframework.context.annotation.Configuration; 6 | 7 | @Data 8 | @Configuration 9 | @ConfigurationProperties(prefix = "retry-config") 10 | public class RetryConfigData { 11 | 12 | private Long initialIntervalMs; 13 | private Long maxIntervalMs; 14 | private Double multiplier; 15 | private Integer maxAttempts; 16 | private Long sleepTimeMs; 17 | 18 | } 19 | -------------------------------------------------------------------------------- /microservices/microservices-demo/app-config-data/src/main/java/com/microservices/demo/config/UserConfigData.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.config; 2 | 3 | 4 | import lombok.Data; 5 | import org.springframework.boot.context.properties.ConfigurationProperties; 6 | import org.springframework.context.annotation.Configuration; 7 | 8 | @Data 9 | @Configuration 10 | @ConfigurationProperties(prefix = "user-config") 11 | public class UserConfigData { 12 | private String username; 13 | private String password; 14 | private String[] roles; 15 | } 16 | -------------------------------------------------------------------------------- /microservices/microservices-demo/common-config/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | microservices-demo 7 | com.microservices.demo 8 | 0.0.1-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | common-config 13 | 14 | 15 | 16 | com.microservices.demo 17 | app-config-data 18 | 19 | 20 | 21 | org.springframework.boot 22 | spring-boot 23 | 24 | 25 | 26 | org.springframework.retry 27 | spring-retry 28 | 29 | 30 | 31 | org.springframework.boot 32 | spring-boot-starter-aop 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /microservices/microservices-demo/common-config/src/main/java/com/microservices/demo/common/config/RetryConfig.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.common.config; 2 | 3 | 4 | import com.microservices.demo.config.RetryConfigData; 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.context.annotation.Configuration; 7 | import org.springframework.retry.backoff.ExponentialBackOffPolicy; 8 | import org.springframework.retry.policy.SimpleRetryPolicy; 9 | import org.springframework.retry.support.RetryTemplate; 10 | 11 | @Configuration 12 | public class RetryConfig { 13 | 14 | private final RetryConfigData retryConfigData; 15 | 16 | public RetryConfig(RetryConfigData retryConfigData) { 17 | this.retryConfigData = retryConfigData; 18 | } 19 | 20 | @Bean 21 | public RetryTemplate retryTemplate() { 22 | RetryTemplate retryTemplate = new RetryTemplate(); 23 | 24 | ExponentialBackOffPolicy exponentialBackOffPolicy = new ExponentialBackOffPolicy(); 25 | exponentialBackOffPolicy.setInitialInterval(retryConfigData.getInitialIntervalMs()); 26 | exponentialBackOffPolicy.setMaxInterval(retryConfigData.getMaxIntervalMs()); 27 | exponentialBackOffPolicy.setMultiplier(retryConfigData.getMultiplier()); 28 | 29 | retryTemplate.setBackOffPolicy(exponentialBackOffPolicy); 30 | 31 | SimpleRetryPolicy simpleRetryPolicy = new SimpleRetryPolicy(); 32 | simpleRetryPolicy.setMaxAttempts(retryConfigData.getMaxAttempts()); 33 | 34 | retryTemplate.setRetryPolicy(simpleRetryPolicy); 35 | 36 | return retryTemplate; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /microservices/microservices-demo/common-util/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | microservices-demo 7 | com.microservices.demo 8 | 0.0.1-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | common-util 13 | 14 | 15 | -------------------------------------------------------------------------------- /microservices/microservices-demo/common-util/src/main/java/com/microservices/demo/common/util/CollectionsUtil.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.common.util; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | public class CollectionsUtil { 7 | 8 | private CollectionsUtil(){ 9 | 10 | } 11 | 12 | private static class CollectionUtilHolder { 13 | private static final CollectionsUtil INSTANCE = new CollectionsUtil(); 14 | } 15 | 16 | public static CollectionsUtil getInstance() { 17 | return CollectionUtilHolder.INSTANCE; 18 | } 19 | 20 | public List getListFromIterable(Iterable iterable) { 21 | List list = new ArrayList<>(); 22 | iterable.forEach(list::add); 23 | return list; 24 | } 25 | 26 | 27 | 28 | } 29 | -------------------------------------------------------------------------------- /microservices/microservices-demo/config-repository-files/config-client-elastic_query_web.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 8184 3 | servlet: 4 | context-path: /elastic-query-web-client 5 | 6 | elastic-query-web-client: 7 | webclient: 8 | connect-timeout-ms: 10000 9 | read-timeout-ms: 10000 10 | write-timeout-ms: 10000 11 | max-in-memory-size: 10485760 # 10MB 12 | content-type: 'application/json' 13 | accept-type: 'application/json' 14 | base-url: 'http://elastic-query-service-1:8183/elastic-query-service/documents' 15 | query-by-text: 16 | method: POST 17 | uri: "/get-document-by-text" 18 | accept: ${elastic-query-web-client.webclient.accept-type} 19 | 20 | spring: 21 | cloud: 22 | loadbalancer: 23 | ribbon: 24 | enabled: false 25 | banner: 26 | location: classpath:banner.txt 27 | thymeleaf: 28 | cache: false 29 | security: 30 | oauth2: 31 | client: 32 | registration: 33 | keycloak: 34 | client-id: 'elastic-query-web-client' 35 | client-secret: 'REwKYcO7xZKijq6DV91N6dzl3TBBxser' 36 | authorization-grant-type: authorization_code 37 | redirect-uri: '{baseUrl}/login/oauth2/code/{registrationId}' 38 | scope: openid 39 | provider: 40 | keycloak: 41 | issuerUri: http://localhost:8080/realms/microservices-realm 42 | 43 | 44 | security: 45 | logout-success-url: http://elastic-query-web-client:8184/elastic-query-web-client 46 | default-client-registration-id: keycloak 47 | 48 | user-config: 49 | username: user 50 | password: password 51 | roles: USER -------------------------------------------------------------------------------- /microservices/microservices-demo/config-repository-files/config-client-finance_stream_service.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | cloud: 3 | loadbalancer: 4 | ribbon: 5 | enabled: false 6 | banner: 7 | location: classpath:banner.txt 8 | server: 9 | port: 3333 10 | 11 | finance-share: 12 | share-list: 13 | - SASA 14 | - SISE 15 | - ANGEN 16 | - EREGL 17 | url-append: .E.BIST 18 | 19 | retry-config: 20 | initial-interval-ms: 1000 21 | max-interval-ms: 10000 22 | multiplier: 2.0 23 | max-attempts: 5 24 | sleep-time-ms: 2000 25 | 26 | kafka-config: 27 | bootstrap-servers: localhost:19092, localhost:29092, localhost:39092 28 | schema-registry-url-key: schema.registry.url 29 | schema-registry-url: http://localhost:8081 30 | topic-name: finance-topic 31 | topic-names-to-create: 32 | - finance-topic 33 | - finance-analytics-topic 34 | num-of-partitions: 3 35 | replication-factor: 3 36 | 37 | 38 | kafka-producer-config: 39 | key-serializer-class: org.apache.kafka.common.serialization.StringSerializer 40 | value-serializer-class: io.confluent.kafka.serializers.KafkaAvroSerializer 41 | compression-type: snappy 42 | acks: all 43 | batch-size: 16384 44 | batch-size-boost-factor: 100 45 | linger-ms: 5 46 | request-timeout-ms: 60000 47 | retry-count: 5 48 | 49 | kafka-consumer-config: 50 | key-deserializer: org.apache.kafka.common.serialization.StringDeserializer 51 | value-deserializer: io.confluent.kafka.serializers.KafkaAvroDeserializer 52 | consumer-group-id: finance-topic-consumer 53 | auto-offset-reset: earliest 54 | specific-avro-reader-key: specific.avro.reader 55 | specific-avro-reader: true 56 | batch-listener: true 57 | auto-startup: false 58 | concurrency-level: 3 59 | session-timeout-ms: 10000 60 | heartbeat-interval-ms: 3000 61 | max-poll-interval-ms: 300000 62 | max-poll-records: 500 63 | max-partition-fetch-bytes-default: 1048576 64 | max-partition-fetch-bytes-boost-factor: 1 65 | poll-timeout-ms: 150 66 | 67 | -------------------------------------------------------------------------------- /microservices/microservices-demo/config-repository-files/config-client-kafka_streams_service.yml: -------------------------------------------------------------------------------- 1 | kafka-streams-service: 2 | custom-audience: kafka-streams-service 3 | 4 | server: 5 | port: 8187 6 | servlet: 7 | context-path: /kafka-streams-service 8 | 9 | 10 | 11 | 12 | spring: 13 | cloud: 14 | loadbalancer: 15 | ribbon: 16 | enabled: false 17 | banner: 18 | location: classpath:banner.txt 19 | security: 20 | oauth2: 21 | resourceserver: 22 | jwt: 23 | issuer-uri: http://localhost:8080/realms/microservices-realm 24 | jwk-set-uri: http://localhost:8080/realms/microservices-realm/protocol/openid-connect/certs 25 | 26 | springdoc: 27 | api-docs: 28 | path: /api-docs 29 | swagger-ui: 30 | path: /swagger-ui.html 31 | 32 | security: 33 | paths-to-ignore: /api-docs, /actuator/** 34 | 35 | management: 36 | endpoints: 37 | web: 38 | base-path: /actuator 39 | exposure.include: health, prometheus 40 | path-mapping.prometheus: metrics 41 | endpoint: 42 | health: 43 | show-details: always 44 | prometheus: 45 | cache.time-to-live: 1ms 46 | 47 | 48 | retry-config: 49 | initial-interval-ms: 1000 50 | max-interval-ms: 10000 51 | multiplier: 2.0 52 | maxAttempts: 3 53 | sleep-time-ms: 2000 54 | 55 | kafka-config: 56 | bootstrap-servers: localhost:19092, localhost:29092, localhost:39092 57 | schema-registry-url-key: schema.registry.url 58 | schema-registry-url: http://localhost:8081 59 | topic-names-to-create: 60 | - finance-topic 61 | - finance-analytics-topic 62 | 63 | kafka-streams-config: 64 | application-id: finance-streams-application 65 | input-topic-name: finance-topic 66 | output-topic-name: finance-analytics-topic 67 | state-file-location: ${HOME}/kafka-streaming-state 68 | word-count-store-name: word-count-store -------------------------------------------------------------------------------- /microservices/microservices-demo/config-repository-files/config-client-kafka_to_elastic.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 8182 3 | 4 | 5 | kafka-config: 6 | bootstrap-servers: localhost:19092, localhost:29092, localhost:39092 7 | schema-registry-url-key: schema.registry.url 8 | schema-registry-url: http://localhost:8081 9 | topic-name: finance-topic 10 | topic-names-to-create: 11 | - finance-topic 12 | 13 | kafka-consumer-config: 14 | key-deserializer: org.apache.kafka.common.serialization.StringDeserializer 15 | value-deserializer: io.confluent.kafka.serializers.KafkaAvroDeserializer 16 | consumer-group-id: finance-topic-consumer 17 | auto-offset-reset: earliest 18 | specific-avro-reader-key: specific.avro.reader 19 | specific-avro-reader: true 20 | batch-listener: true 21 | auto-startup: true 22 | concurrency-level: 3 23 | session-timeout-ms: 10000 24 | heartbeat-interval-ms: 3000 25 | max-poll-interval-ms: 300000 26 | max-poll-records: 500 27 | max-partition-fetch-bytes-default: 1048576 28 | max-partition-fetch-bytes-boost-factor: 1 29 | poll-timeout-ms: 150 30 | 31 | retry-config: 32 | initial-interval-ms: 1000 33 | max-interval-ms: 10000 34 | multiplier: 2.0 35 | maxAttempts: 3 36 | sleep-time-ms: 2000 37 | 38 | elastic-config: 39 | index-name: bist-index 40 | connection-url: http://elastic-1:9200 41 | connect-timeout-ms: 5000 42 | socket-timeout-ms: 30000 43 | is-repository: true 44 | 45 | spring: 46 | cloud: 47 | loadbalancer: 48 | ribbon: 49 | enabled: false 50 | banner: 51 | location: classpath:banner.txt -------------------------------------------------------------------------------- /microservices/microservices-demo/config-repository-files/config-client-reactive_elastic_query.yml: -------------------------------------------------------------------------------- 1 | elastic-query-service: 2 | backPressure-delay-ms: 500 3 | 4 | elastic-config: 5 | index-name: bist-index 6 | connection-url: http://elastic-1:9200 7 | connect-timeout-ms: 5000 8 | socket-timeout-ms: 30000 9 | 10 | elastic-query-config: 11 | text-field: shareData.c 12 | 13 | kafka-config: 14 | topic-name: finance-analytics-topic-2 15 | topic-names-to-create: 16 | - finance-analytics-topic-2 17 | num-partitions: 3 18 | replication-factor: 3 19 | bootstrap-servers: localhost:19092, localhost:29092, localhost:39092 20 | schema-registry-servers: http://localhost:8081 21 | sleep-time-ms: 1000 22 | max-interval-ms: 10000 23 | retry-multiplier: 2.0 24 | admin-retry-max: 1 25 | 26 | server: 27 | port: 8183 28 | 29 | spring: 30 | banner: 31 | location: classpath:banner.txt 32 | webflux: 33 | base-path: /reactive-elastic-query-service 34 | codec: 35 | max-in-memory-size: 25MB 36 | data: 37 | elasticsearch: 38 | client: 39 | reactive: 40 | max-in-memory-size: 25MB -------------------------------------------------------------------------------- /microservices/microservices-demo/config-repository-files/config-client-reactive_elastic_query_web.yml: -------------------------------------------------------------------------------- 1 | elastic-query-web-client: 2 | webclient: 3 | connect-timeout-ms: 10000 4 | read-timeout-ms: 10000 5 | write-timeout-ms: 10000 6 | max-in-memory-size: 10485760 # 10MB 7 | content-type: 'application/json' 8 | accept-type: 'text/event-stream' 9 | base-url: 'http://localhost:8183/reactive-elastic-query-service/documents' 10 | query-by-text: 11 | method: POST 12 | uri: "/get-doc-by-text" 13 | accept: 'text/event-stream' 14 | 15 | server: 16 | port: 8184 17 | 18 | spring: 19 | banner: 20 | location: classpath:banner.txt 21 | webflux: 22 | base-path: /reactive-elastic-query-web-client 23 | thymeleaf: 24 | cache: false 25 | reactive: 26 | max-chunk-size: 8192 27 | codec: 28 | max-in-memory-size: 25MB -------------------------------------------------------------------------------- /microservices/microservices-demo/config-repository-files/config-client.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | cloud: 3 | config: 4 | allow-override: true 5 | override-none: true -------------------------------------------------------------------------------- /microservices/microservices-demo/config-server/src/main/java/com/microservices/demo/config/server/ConfigServer.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.config.server; 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.config.server.EnableConfigServer; 7 | 8 | @EnableConfigServer 9 | @EnableDiscoveryClient 10 | @SpringBootApplication 11 | public class ConfigServer { 12 | public static void main(String[] args) { 13 | SpringApplication.run(ConfigServer.class, args); 14 | } 15 | } -------------------------------------------------------------------------------- /microservices/microservices-demo/config-server/src/main/java/com/microservices/demo/config/server/config/SecurityConfig.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.config.server.config; 2 | 3 | import org.springframework.context.annotation.Configuration; 4 | import org.springframework.security.config.annotation.web.builders.WebSecurity; 5 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; 6 | 7 | @Configuration 8 | public class SecurityConfig extends WebSecurityConfigurerAdapter { 9 | 10 | @Override 11 | public void configure(WebSecurity web) throws Exception { 12 | web.ignoring() 13 | .antMatchers("/actuator/**") 14 | .antMatchers("/encrypt/**") 15 | .antMatchers("/decrypt/**"); 16 | super.configure(web); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /microservices/microservices-demo/config-server/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | banner: 3 | location: classpath:banner.txt 4 | security: 5 | user: 6 | name: spring_cloud_user 7 | password: spring_cloud_password 8 | application: 9 | name: config-server 10 | cloud: 11 | config: 12 | server: 13 | git: 14 | uri: <%= git.uri %> 15 | username: 16 | password: 17 | clone-on-start: true 18 | default-label: main 19 | fail-fast: true 20 | server: 21 | port: 8888 22 | logging: 23 | level: 24 | ROOT: INFO 25 | org.spring.framework.cloud.config: DEBUG 26 | 27 | 28 | eureka: 29 | client: 30 | serviceUrl: 31 | defaultZone: http://localhost:8761/eureka/ 32 | instance: 33 | lease-expiration-duration-in-seconds: 5 34 | lease-renewal-interval-in-seconds: 2 -------------------------------------------------------------------------------- /microservices/microservices-demo/config-server/src/main/resources/banner.txt: -------------------------------------------------------------------------------- 1 | _ _ _ ___ _ _ _ _ ___ 2 | /_\ | | (_) / __| /_\ | \| | | | |_ _| 3 | / _ \ | | | | | (__ / _ \ | .` | | |__ | | 4 | /_/ \_\ |_| |_| \___| /_/ \_\ |_|\_| |____| |___| 5 | 6 | ${application.title} ${application.version} 7 | Powered by Spring Boot ${spring-boot.version} -------------------------------------------------------------------------------- /microservices/microservices-demo/config-server/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /microservices/microservices-demo/discovery-service/src/main/java/com/microservices/demo/discovery/service/DiscoveryClientApp.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.discovery.service; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; 6 | 7 | @EnableEurekaServer 8 | @SpringBootApplication 9 | public class DiscoveryClientApp { 10 | public static void main(String[] args) { 11 | SpringApplication.run(DiscoveryClientApp.class, args); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /microservices/microservices-demo/discovery-service/src/main/resources/application-singleserver.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 8761 3 | 4 | eureka: 5 | client: 6 | register-with-eureka: false 7 | fetch-registry: false 8 | instance: 9 | appname: service-registry-cluster 10 | 11 | logging: 12 | level: 13 | com.netflix.eureka: OFF 14 | com.netflix.discovery: OFF 15 | spring: 16 | banner: 17 | location: classpath:banner.txt -------------------------------------------------------------------------------- /microservices/microservices-demo/discovery-service/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | eureka: 2 | client: 3 | register-with-eureka: true 4 | fetch-registry: true 5 | instance: 6 | appname: service-registry-cluster 7 | server: 8 | enable-self-preservation: false 9 | expected-client-renewal-interval-seconds: 3 10 | eviction-interval-timer-in-ms: 2000 11 | 12 | spring: 13 | banner: 14 | location: classpath:banner.txt 15 | cloud: 16 | loadbalancer: 17 | ribbon: 18 | enabled: false 19 | profiles: 20 | active: singleserver 21 | 22 | 23 | --- 24 | server: 25 | port: 8761 26 | spring: 27 | profiles: peer1 28 | eureka: 29 | instance: 30 | hostname: discovery-service-1 31 | metadataMap: 32 | instanceId: ${spring.application.name}:${spring.application.instance_id:${random.value}} 33 | client: 34 | serviceUrl: 35 | defaultZone: http://discovery-service-1:8761/eureka/,http://discovery-service-2:8762/eureka/ 36 | 37 | --- 38 | server: 39 | port: 8762 40 | spring: 41 | profiles: peer2 42 | eureka: 43 | instance: 44 | hostname: discovery-service-2 45 | metadataMap: 46 | instanceId: ${spring.application.name}:${spring.application.instance_id:${random.value}} 47 | client: 48 | serviceUrl: 49 | defaultZone: http://discovery-service-2:8762/eureka/,http://discovery-service-1:8761/eureka/ 50 | -------------------------------------------------------------------------------- /microservices/microservices-demo/discovery-service/src/main/resources/banner.txt: -------------------------------------------------------------------------------- 1 | _ _ _ ___ _ _ _ _ ___ 2 | /_\ | | (_) / __| /_\ | \| | | | |_ _| 3 | / _ \ | | | | | (__ / _ \ | .` | | |__ | | 4 | /_/ \_\ |_| |_| \___| /_/ \_\ |_|\_| |____| |___| 5 | 6 | ${application.title} ${application.version} 7 | Powered by Spring Boot ${spring-boot.version} -------------------------------------------------------------------------------- /microservices/microservices-demo/elastic-query-service-common/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | microservices-demo 7 | com.microservices.demo 8 | 0.0.1-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | elastic-query-service-common 13 | 14 | 15 | 16 | com.microservices.demo 17 | elastic-model 18 | 19 | 20 | org.projectlombok 21 | lombok 22 | 23 | 24 | org.springframework 25 | spring-context 26 | 27 | 28 | org.springframework 29 | spring-web 30 | 31 | 32 | org.springframework.security 33 | spring-security-core 34 | 35 | 36 | org.springframework.hateoas 37 | spring-hateoas 38 | 39 | 40 | org.springframework.boot 41 | spring-boot-starter-validation 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /microservices/microservices-demo/elastic-query-service-common/src/main/java/com/microservices/demo/elastic/query/service/common/api/error/handler/ElasticQueryServiceHandler.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.elastic.query.service.common.api.error.handler; 2 | 3 | import lombok.extern.slf4j.Slf4j; 4 | import org.springframework.http.HttpStatus; 5 | import org.springframework.http.ResponseEntity; 6 | import org.springframework.security.access.AccessDeniedException; 7 | import org.springframework.web.bind.MethodArgumentNotValidException; 8 | import org.springframework.web.bind.annotation.ControllerAdvice; 9 | import org.springframework.web.bind.annotation.ExceptionHandler; 10 | 11 | import java.util.HashMap; 12 | 13 | @Slf4j 14 | @ControllerAdvice 15 | public class ElasticQueryServiceHandler { 16 | 17 | @ExceptionHandler(AccessDeniedException.class) 18 | public ResponseEntity handle(AccessDeniedException e) { 19 | log.error("Access denied exception", e); 20 | return ResponseEntity.status(HttpStatus.FORBIDDEN).body(e.getMessage()); 21 | } 22 | 23 | @ExceptionHandler(IllegalArgumentException.class) 24 | public ResponseEntity handle(IllegalArgumentException e) { 25 | log.error("Illegal argument exception", e); 26 | return ResponseEntity.badRequest().body(e.getMessage()); 27 | } 28 | 29 | @ExceptionHandler(RuntimeException.class) 30 | public ResponseEntity handle(RuntimeException e) { 31 | log.error("Runtime exception", e); 32 | return ResponseEntity.badRequest().body(e.getMessage()); 33 | } 34 | 35 | @ExceptionHandler(MethodArgumentNotValidException.class) 36 | public ResponseEntity handle(MethodArgumentNotValidException e) { 37 | log.error("Method argument not valid exception", e); 38 | var errors = new HashMap(); 39 | e.getBindingResult().getAllErrors().forEach(error -> { 40 | errors.put(error.getObjectName(), error.getDefaultMessage()); 41 | }); 42 | return ResponseEntity.badRequest().body(errors.toString()); 43 | } 44 | 45 | @ExceptionHandler(Exception.class) 46 | public ResponseEntity handle(Exception e) { 47 | log.error("Exception", e); 48 | return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(e.getMessage()); 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /microservices/microservices-demo/elastic-query-service-common/src/main/java/com/microservices/demo/elastic/query/service/common/converter/ElasticToResponseModelConverter.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.elastic.query.service.common.converter; 2 | 3 | import com.microservices.demo.elastic.model.index.impl.FinanceIndexModel; 4 | import com.microservices.demo.elastic.model.index.model.FinanceAvroDTO; 5 | import com.microservices.demo.elastic.query.service.common.model.ElasticQueryResponseModel; 6 | import org.springframework.stereotype.Component; 7 | 8 | import java.util.List; 9 | 10 | @Component 11 | public class ElasticToResponseModelConverter { 12 | 13 | public ElasticQueryResponseModel convert(FinanceIndexModel financeIndexModel) { 14 | return ElasticQueryResponseModel.builder() 15 | .id(financeIndexModel.getId()) 16 | .shareData( 17 | FinanceAvroDTO.builder() 18 | .dailyChangePercentage(financeIndexModel.getShareData().getDailyChangePercentage()) 19 | .dailyChange(financeIndexModel.getShareData().getDailyChange()) 20 | .c(financeIndexModel.getShareData().getC()) 21 | .last(financeIndexModel.getShareData().getLast()) 22 | .dailyVolume(financeIndexModel.getShareData().getDailyVolume()) 23 | .previousDayClose(financeIndexModel.getShareData().getPreviousDayClose()) 24 | .description(financeIndexModel.getShareData().getDescription()) 25 | .build() 26 | ) 27 | .createdAt(financeIndexModel.getCreatedAt()) 28 | .build(); 29 | } 30 | 31 | public List convert(List financeIndexModels) { 32 | return financeIndexModels.stream() 33 | .map(this::convert) 34 | .toList(); 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /microservices/microservices-demo/elastic-query-service-common/src/main/java/com/microservices/demo/elastic/query/service/common/model/ElasticQueryRequestModel.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.elastic.query.service.common.model; 2 | 3 | import com.microservices.demo.elastic.model.index.model.FinanceAvroDTO; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Builder; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | import javax.validation.constraints.NotNull; 10 | import java.time.ZonedDateTime; 11 | 12 | @Data 13 | @Builder 14 | @NoArgsConstructor 15 | @AllArgsConstructor 16 | public class ElasticQueryRequestModel { 17 | 18 | private String id; 19 | @NotNull 20 | private FinanceAvroDTO shareData; 21 | private ZonedDateTime createdAt; 22 | 23 | } 24 | -------------------------------------------------------------------------------- /microservices/microservices-demo/elastic-query-service-common/src/main/java/com/microservices/demo/elastic/query/service/common/model/ElasticQueryResponseModel.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.elastic.query.service.common.model; 2 | 3 | import com.microservices.demo.elastic.model.index.model.FinanceAvroDTO; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Builder; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | import org.springframework.hateoas.RepresentationModel; 9 | 10 | import java.time.ZonedDateTime; 11 | 12 | @Data 13 | @Builder 14 | @NoArgsConstructor 15 | @AllArgsConstructor 16 | public class ElasticQueryResponseModel extends RepresentationModel { 17 | private String id; 18 | private FinanceAvroDTO shareData; 19 | private ZonedDateTime createdAt; 20 | } 21 | -------------------------------------------------------------------------------- /microservices/microservices-demo/elastic-query-service-reactive/src/main/java/com/microservices/demo/elastic/query/service/reactive/ElasticQueryServiceReactiveApplication.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.elastic.query.service.reactive; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.context.annotation.ComponentScan; 6 | 7 | @SpringBootApplication 8 | @ComponentScan(basePackages = {"com.microservices.demo"}) 9 | public class ElasticQueryServiceReactiveApplication { 10 | public static void main(String[] args) { 11 | SpringApplication.run(ElasticQueryServiceReactiveApplication.class, args); 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /microservices/microservices-demo/elastic-query-service-reactive/src/main/java/com/microservices/demo/elastic/query/service/reactive/config/WebSecurityConfig.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.elastic.query.service.reactive.config; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.security.config.web.server.ServerHttpSecurity; 6 | import org.springframework.security.web.server.SecurityWebFilterChain; 7 | 8 | @Configuration 9 | public class WebSecurityConfig { 10 | 11 | @Bean 12 | public SecurityWebFilterChain webFluxSecurityConfig(ServerHttpSecurity httpSecurity) { 13 | httpSecurity.authorizeExchange() 14 | .anyExchange() 15 | .permitAll(); 16 | httpSecurity.csrf().disable(); 17 | return httpSecurity.build(); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /microservices/microservices-demo/elastic-query-service-reactive/src/main/java/com/microservices/demo/elastic/query/service/reactive/controller/ElasticDocumentControllerReactive.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.elastic.query.service.reactive.controller; 2 | 3 | import com.microservices.demo.elastic.query.service.common.model.ElasticQueryRequestModel; 4 | import com.microservices.demo.elastic.query.service.common.model.ElasticQueryResponseModel; 5 | import com.microservices.demo.elastic.query.service.reactive.service.ElasticQueryService; 6 | import lombok.RequiredArgsConstructor; 7 | import lombok.extern.slf4j.Slf4j; 8 | import org.springframework.http.MediaType; 9 | import org.springframework.validation.annotation.Validated; 10 | import org.springframework.web.bind.annotation.PostMapping; 11 | import org.springframework.web.bind.annotation.RequestBody; 12 | import org.springframework.web.bind.annotation.RequestMapping; 13 | import org.springframework.web.bind.annotation.RestController; 14 | import reactor.core.publisher.Flux; 15 | 16 | import javax.validation.Valid; 17 | 18 | @Slf4j 19 | @Validated 20 | @RestController 21 | @RequestMapping(value = "/documents") 22 | @RequiredArgsConstructor 23 | public class ElasticDocumentControllerReactive { 24 | private final ElasticQueryService elasticQueryService; 25 | 26 | @PostMapping(value = "/get-doc-by-text", 27 | produces = MediaType.TEXT_EVENT_STREAM_VALUE, 28 | consumes = MediaType.APPLICATION_JSON_VALUE) 29 | public Flux getDocumentByText( 30 | @RequestBody @Valid ElasticQueryRequestModel requestModel) { 31 | Flux response = 32 | elasticQueryService.getDocumentByShareData(requestModel.getShareData().getC()); 33 | response = response.log(); 34 | log.info("Returning from query reactive service for text {}!", requestModel.getShareData().getC()); 35 | return response; 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /microservices/microservices-demo/elastic-query-service-reactive/src/main/java/com/microservices/demo/elastic/query/service/reactive/repository/ElasticQueryRepository.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.elastic.query.service.reactive.repository; 2 | 3 | import com.microservices.demo.elastic.model.index.impl.FinanceIndexModel; 4 | import org.springframework.data.repository.reactive.ReactiveCrudRepository; 5 | import org.springframework.stereotype.Repository; 6 | import reactor.core.publisher.Flux; 7 | 8 | @Repository 9 | public interface ElasticQueryRepository extends ReactiveCrudRepository { 10 | 11 | Flux findByShareDataCIn(String c); 12 | 13 | } 14 | -------------------------------------------------------------------------------- /microservices/microservices-demo/elastic-query-service-reactive/src/main/java/com/microservices/demo/elastic/query/service/reactive/service/ElasticQueryService.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.elastic.query.service.reactive.service; 2 | 3 | import com.microservices.demo.elastic.query.service.common.model.ElasticQueryResponseModel; 4 | import reactor.core.publisher.Flux; 5 | 6 | public interface ElasticQueryService { 7 | Flux getDocumentByShareData(String text); 8 | 9 | } 10 | -------------------------------------------------------------------------------- /microservices/microservices-demo/elastic-query-service-reactive/src/main/java/com/microservices/demo/elastic/query/service/reactive/service/ReactiveElasticQueryClient.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.elastic.query.service.reactive.service; 2 | 3 | import com.microservices.demo.elastic.model.index.IndexModel; 4 | import com.microservices.demo.elastic.model.index.impl.FinanceIndexModel; 5 | import reactor.core.publisher.Flux; 6 | 7 | public interface ReactiveElasticQueryClient { 8 | Flux getIndexModelByText(String text); 9 | } 10 | -------------------------------------------------------------------------------- /microservices/microservices-demo/elastic-query-service-reactive/src/main/java/com/microservices/demo/elastic/query/service/reactive/service/impl/FinanceElasticQueryService.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.elastic.query.service.reactive.service.impl; 2 | 3 | 4 | import com.microservices.demo.elastic.model.index.impl.FinanceIndexModel; 5 | import com.microservices.demo.elastic.query.service.common.converter.ElasticToResponseModelConverter; 6 | import com.microservices.demo.elastic.query.service.common.model.ElasticQueryResponseModel; 7 | import com.microservices.demo.elastic.query.service.reactive.service.ElasticQueryService; 8 | import com.microservices.demo.elastic.query.service.reactive.service.ReactiveElasticQueryClient; 9 | import lombok.RequiredArgsConstructor; 10 | import lombok.extern.slf4j.Slf4j; 11 | import org.springframework.stereotype.Service; 12 | import reactor.core.publisher.Flux; 13 | 14 | @Slf4j 15 | @Service 16 | @RequiredArgsConstructor 17 | public class FinanceElasticQueryService implements ElasticQueryService { 18 | 19 | private final ReactiveElasticQueryClient reactiveElasticQueryClient; 20 | 21 | private final ElasticToResponseModelConverter elasticToResponseModelTransformer; 22 | 23 | @Override 24 | public Flux getDocumentByShareData(String text) { 25 | return reactiveElasticQueryClient 26 | .getIndexModelByText(text) 27 | .map(elasticToResponseModelTransformer::convert); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /microservices/microservices-demo/elastic-query-service-reactive/src/main/java/com/microservices/demo/elastic/query/service/reactive/service/impl/FinanceReactiveElasticQueryClient.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.elastic.query.service.reactive.service.impl; 2 | 3 | import com.microservices.demo.config.ElasticQueryServiceConfigData; 4 | import com.microservices.demo.elastic.model.index.impl.FinanceIndexModel; 5 | import com.microservices.demo.elastic.query.service.reactive.repository.ElasticQueryRepository; 6 | import com.microservices.demo.elastic.query.service.reactive.service.ReactiveElasticQueryClient; 7 | import lombok.RequiredArgsConstructor; 8 | import lombok.extern.slf4j.Slf4j; 9 | import org.springframework.stereotype.Service; 10 | import reactor.core.publisher.Flux; 11 | 12 | import java.time.Duration; 13 | 14 | @Slf4j 15 | @Service 16 | @RequiredArgsConstructor 17 | public class FinanceReactiveElasticQueryClient implements ReactiveElasticQueryClient { 18 | 19 | private final ElasticQueryRepository elasticQueryRepository; 20 | 21 | private final ElasticQueryServiceConfigData elasticQueryServiceConfigData; 22 | 23 | @Override 24 | public Flux getIndexModelByText(String c) { 25 | log.info("Getting data from elasticsearch for text {}", c); 26 | return elasticQueryRepository 27 | .findByShareDataCIn(c) 28 | .delayElements(Duration.ofMillis(elasticQueryServiceConfigData.getBackPressureDelayMs())); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /microservices/microservices-demo/elastic-query-service-reactive/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: reactive-elastic-query-service 4 | profiles: 5 | active: reactive_elastic_query 6 | cloud: 7 | config: 8 | name: reactive-elastic-query-service,config-client 9 | uri: http://config-server:8888 10 | enabled: true 11 | username: spring_cloud_user 12 | password: spring_cloud_password 13 | config: 14 | import: configserver:http://config-server:8888 15 | 16 | -------------------------------------------------------------------------------- /microservices/microservices-demo/elastic-query-service-reactive/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /microservices/microservices-demo/elastic-query-service-reactive/src/test/java/com/microservices/demo/elastic/query/service/reactive/ElasticQueryServiceReactiveApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.elastic.query.service.reactive; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | public class ElasticQueryServiceReactiveApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /microservices/microservices-demo/elastic-query-service/src/main/java/com/microservices/demo/elastic/query/service/ElasticQueryServiceApp.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.elastic.query.service; 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.context.annotation.ComponentScan; 7 | 8 | @EnableDiscoveryClient 9 | @SpringBootApplication 10 | @ComponentScan(basePackages = {"com.microservices.demo"}) 11 | public class ElasticQueryServiceApp { 12 | 13 | public static void main(String[] args) { 14 | SpringApplication.run(ElasticQueryServiceApp.class, args); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /microservices/microservices-demo/elastic-query-service/src/main/java/com/microservices/demo/elastic/query/service/converter/UserPermissionToUserDetailConverter.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.elastic.query.service.converter; 2 | 3 | import com.microservices.demo.elastic.query.service.dataaccess.entity.UserPermission; 4 | import com.microservices.demo.elastic.query.service.security.FinanceQueryUser; 5 | import com.microservices.demo.elastic.query.service.security.PermissionType; 6 | import org.springframework.stereotype.Component; 7 | 8 | import java.util.List; 9 | import java.util.stream.Collectors; 10 | 11 | @Component 12 | public class UserPermissionToUserDetailConverter { 13 | 14 | public FinanceQueryUser getUserDetails(List userPermissions) { 15 | if (userPermissions.isEmpty()) { 16 | return FinanceQueryUser.builder().build(); 17 | } 18 | return FinanceQueryUser.builder() 19 | .username(userPermissions.get(0).getUsername()) 20 | .permissions(userPermissions.stream() 21 | .collect(Collectors.toMap( 22 | UserPermission::getDocumentId, 23 | permission -> PermissionType.valueOf(permission.getPermissionType())))) 24 | .build(); 25 | } 26 | 27 | 28 | } 29 | -------------------------------------------------------------------------------- /microservices/microservices-demo/elastic-query-service/src/main/java/com/microservices/demo/elastic/query/service/dataaccess/entity/UserPermission.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.elastic.query.service.dataaccess.entity; 2 | 3 | import lombok.*; 4 | import org.hibernate.Hibernate; 5 | import org.hibernate.annotations.DynamicUpdate; 6 | 7 | import javax.persistence.Entity; 8 | import javax.persistence.Id; 9 | import javax.validation.constraints.NotNull; 10 | import java.util.Objects; 11 | import java.util.UUID; 12 | 13 | @Entity 14 | @Getter 15 | @Setter 16 | @ToString 17 | @DynamicUpdate 18 | @RequiredArgsConstructor 19 | public class UserPermission { 20 | 21 | @Id 22 | @NotNull 23 | private UUID id; 24 | 25 | @NotNull 26 | private String username; 27 | 28 | @NotNull 29 | private String documentId; 30 | 31 | @NotNull 32 | private String permissionType; 33 | 34 | @Override 35 | public boolean equals(Object o) { 36 | if (this == o) return true; 37 | if (o == null || Hibernate.getClass(this) != Hibernate.getClass(o)) return false; 38 | UserPermission that = (UserPermission) o; 39 | return id != null && Objects.equals(id, that.id); 40 | } 41 | 42 | @Override 43 | public int hashCode() { 44 | return getClass().hashCode(); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /microservices/microservices-demo/elastic-query-service/src/main/java/com/microservices/demo/elastic/query/service/dataaccess/repository/UserPermissionRepository.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.elastic.query.service.dataaccess.repository; 2 | 3 | import com.microservices.demo.elastic.query.service.dataaccess.entity.UserPermission; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | import org.springframework.data.repository.query.Param; 6 | import org.springframework.stereotype.Repository; 7 | import org.springframework.data.jpa.repository.Query; 8 | 9 | import java.util.List; 10 | import java.util.Optional; 11 | import java.util.UUID; 12 | 13 | @Repository 14 | public interface UserPermissionRepository extends JpaRepository { 15 | 16 | @Query(nativeQuery = true, value = 17 | "select p.user_permission_id as id, u.username, d.document_id, p.permission_type " + 18 | "from users u, user_permissions p, documents d " + 19 | "where u.id = p.user_id " + 20 | "and d.id = p.document_id " + 21 | "and u.username = :username") 22 | Optional> findUserPermissionByUsername(@Param("username") String username); 23 | } 24 | -------------------------------------------------------------------------------- /microservices/microservices-demo/elastic-query-service/src/main/java/com/microservices/demo/elastic/query/service/model/ElasticQueryServiceAnalyticsResponseModel.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.elastic.query.service.model; 2 | 3 | 4 | import lombok.AllArgsConstructor; 5 | import lombok.Builder; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | @Data 10 | @Builder 11 | @NoArgsConstructor 12 | @AllArgsConstructor 13 | public class ElasticQueryServiceAnalyticsResponseModel { 14 | private String queryResponseModels; 15 | private String shareVolume; 16 | } 17 | -------------------------------------------------------------------------------- /microservices/microservices-demo/elastic-query-service/src/main/java/com/microservices/demo/elastic/query/service/model/KafkaStreamsResponseModel.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.elastic.query.service.model; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | @Data 9 | @NoArgsConstructor 10 | @AllArgsConstructor 11 | @Builder 12 | public class KafkaStreamsResponseModel { 13 | private String shareName; 14 | private String shareVolume; 15 | } 16 | -------------------------------------------------------------------------------- /microservices/microservices-demo/elastic-query-service/src/main/java/com/microservices/demo/elastic/query/service/model/assemblr/ElasticQueryResponseModelAssembler.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.elastic.query.service.model.assemblr; 2 | 3 | import com.microservices.demo.elastic.model.index.impl.FinanceIndexModel; 4 | import com.microservices.demo.elastic.query.service.common.converter.ElasticToResponseModelConverter; 5 | import com.microservices.demo.elastic.query.service.common.model.ElasticQueryResponseModel; 6 | import com.microservices.demo.elastic.query.service.controller.ElasticDocumentController; 7 | import lombok.extern.slf4j.Slf4j; 8 | import org.springframework.hateoas.server.mvc.RepresentationModelAssemblerSupport; 9 | import org.springframework.stereotype.Component; 10 | 11 | import java.util.List; 12 | 13 | import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.linkTo; 14 | import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.methodOn; 15 | 16 | @Slf4j 17 | @Component 18 | public class ElasticQueryResponseModelAssembler extends 19 | RepresentationModelAssemblerSupport { 20 | 21 | private final ElasticToResponseModelConverter elasticToResponseModelConverter; 22 | 23 | public ElasticQueryResponseModelAssembler(ElasticToResponseModelConverter elasticToResponseModelConverter) { 24 | super(ElasticDocumentController.class, ElasticQueryResponseModel.class); 25 | this.elasticToResponseModelConverter = elasticToResponseModelConverter; 26 | } 27 | 28 | 29 | @Override 30 | public ElasticQueryResponseModel toModel(FinanceIndexModel entity) { 31 | ElasticQueryResponseModel responseModel = elasticToResponseModelConverter.convert(entity); 32 | responseModel.add( 33 | linkTo(methodOn(ElasticDocumentController.class) 34 | .getDocumentsById(entity.getId())) 35 | .withSelfRel()); 36 | responseModel.add( 37 | linkTo(ElasticDocumentController.class) 38 | .withRel("documents")); 39 | 40 | return responseModel; 41 | 42 | } 43 | 44 | public List toModels(List financeIndexModels) { 45 | return financeIndexModels 46 | .stream() 47 | .map(this::toModel) 48 | .toList(); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /microservices/microservices-demo/elastic-query-service/src/main/java/com/microservices/demo/elastic/query/service/security/AudienceValidator.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.elastic.query.service.security; 2 | 3 | import com.microservices.demo.config.ElasticQueryServiceConfigData; 4 | import lombok.RequiredArgsConstructor; 5 | import org.springframework.beans.factory.annotation.Qualifier; 6 | import org.springframework.security.oauth2.core.OAuth2Error; 7 | import org.springframework.security.oauth2.core.OAuth2TokenValidator; 8 | import org.springframework.security.oauth2.core.OAuth2TokenValidatorResult; 9 | import org.springframework.security.oauth2.jwt.Jwt; 10 | import org.springframework.stereotype.Component; 11 | 12 | @Component 13 | @RequiredArgsConstructor 14 | @Qualifier("elastic-query-service-audience-validator") 15 | public class AudienceValidator implements OAuth2TokenValidator { 16 | 17 | private final ElasticQueryServiceConfigData configData; 18 | 19 | 20 | @Override 21 | public OAuth2TokenValidatorResult validate(Jwt token) { 22 | if (token.getAudience().contains(configData.getCustomAudience())) { 23 | return OAuth2TokenValidatorResult.success(); 24 | } else { 25 | var error = new OAuth2Error("invalid_token", 26 | "The token does not have the expected audience.", null); 27 | return OAuth2TokenValidatorResult.failure(error); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /microservices/microservices-demo/elastic-query-service/src/main/java/com/microservices/demo/elastic/query/service/security/FinanceQueryUser.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.elastic.query.service.security; 2 | 3 | import lombok.Builder; 4 | import lombok.Getter; 5 | import org.springframework.security.core.GrantedAuthority; 6 | import org.springframework.security.core.userdetails.UserDetails; 7 | 8 | import java.util.Collection; 9 | import java.util.Map; 10 | 11 | import static com.microservices.demo.elastic.query.service.util.Constants.NA; 12 | 13 | @Getter 14 | @Builder 15 | public class FinanceQueryUser implements UserDetails { 16 | 17 | private String username; 18 | 19 | private Collection authorities; 20 | 21 | private Map permissions; 22 | 23 | 24 | public void setAuthorities(Collection authorities) { 25 | this.authorities = authorities; 26 | } 27 | 28 | @Override 29 | public Collection getAuthorities() { 30 | return authorities; 31 | } 32 | 33 | @Override 34 | public String getPassword() { 35 | return NA; 36 | } 37 | 38 | @Override 39 | public String getUsername() { 40 | return username; 41 | } 42 | 43 | @Override 44 | public boolean isAccountNonExpired() { 45 | return true; 46 | } 47 | 48 | @Override 49 | public boolean isAccountNonLocked() { 50 | return true; 51 | } 52 | 53 | @Override 54 | public boolean isCredentialsNonExpired() { 55 | return true; 56 | } 57 | 58 | @Override 59 | public boolean isEnabled() { 60 | return true; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /microservices/microservices-demo/elastic-query-service/src/main/java/com/microservices/demo/elastic/query/service/security/FinanceQueryUserDetailService.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.elastic.query.service.security; 2 | 3 | import com.microservices.demo.elastic.query.service.converter.UserPermissionToUserDetailConverter; 4 | import com.microservices.demo.elastic.query.service.service.QueryUserService; 5 | import lombok.RequiredArgsConstructor; 6 | import lombok.extern.slf4j.Slf4j; 7 | import org.springframework.security.core.userdetails.UserDetails; 8 | import org.springframework.security.core.userdetails.UserDetailsService; 9 | import org.springframework.security.core.userdetails.UsernameNotFoundException; 10 | import org.springframework.stereotype.Service; 11 | 12 | @Slf4j 13 | @Service 14 | @RequiredArgsConstructor 15 | public class FinanceQueryUserDetailService implements UserDetailsService { 16 | 17 | private final QueryUserService queryUserService; 18 | 19 | private final UserPermissionToUserDetailConverter userPermissionsToUserDetailTransformer; 20 | @Override 21 | public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { 22 | return queryUserService 23 | .findAllPermissionsByUsername(username) 24 | .map(userPermissionsToUserDetailTransformer::getUserDetails) 25 | .orElseThrow( 26 | () -> new UsernameNotFoundException("No user found with name " + username)); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /microservices/microservices-demo/elastic-query-service/src/main/java/com/microservices/demo/elastic/query/service/security/PermissionType.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.elastic.query.service.security; 2 | 3 | public enum PermissionType { 4 | 5 | READ("READ"), WRITE("WRITE"), ADMIN("ADMIN"); 6 | 7 | private String type; 8 | 9 | PermissionType(String type) { 10 | this.type = type; 11 | } 12 | 13 | public String getType() { 14 | return this.type; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /microservices/microservices-demo/elastic-query-service/src/main/java/com/microservices/demo/elastic/query/service/service/ElasticQueryService.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.elastic.query.service.service; 2 | 3 | import com.microservices.demo.elastic.query.service.common.model.ElasticQueryResponseModel; 4 | import com.microservices.demo.elastic.query.service.model.ElasticQueryServiceAnalyticsResponseModel; 5 | 6 | import java.util.List; 7 | 8 | public interface ElasticQueryService { 9 | 10 | ElasticQueryResponseModel getDocumentById(String id); 11 | ElasticQueryServiceAnalyticsResponseModel getDocumentsByShareData(String c,String jwt); 12 | List getAllDocuments(); 13 | 14 | } 15 | -------------------------------------------------------------------------------- /microservices/microservices-demo/elastic-query-service/src/main/java/com/microservices/demo/elastic/query/service/service/QueryUserService.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.elastic.query.service.service; 2 | 3 | import com.microservices.demo.elastic.query.service.dataaccess.entity.UserPermission; 4 | 5 | import java.util.List; 6 | import java.util.Optional; 7 | 8 | public interface QueryUserService { 9 | 10 | Optional> findAllPermissionsByUsername(String username); 11 | 12 | } 13 | -------------------------------------------------------------------------------- /microservices/microservices-demo/elastic-query-service/src/main/java/com/microservices/demo/elastic/query/service/service/impl/FinanceQueryUserService.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.elastic.query.service.service.impl; 2 | 3 | import com.microservices.demo.elastic.query.service.dataaccess.entity.UserPermission; 4 | import com.microservices.demo.elastic.query.service.dataaccess.repository.UserPermissionRepository; 5 | import com.microservices.demo.elastic.query.service.service.QueryUserService; 6 | import lombok.RequiredArgsConstructor; 7 | import lombok.extern.slf4j.Slf4j; 8 | import org.springframework.stereotype.Service; 9 | 10 | import java.util.List; 11 | import java.util.Optional; 12 | 13 | @Slf4j 14 | @Service 15 | @RequiredArgsConstructor 16 | public class FinanceQueryUserService implements QueryUserService { 17 | 18 | private final UserPermissionRepository userPermissionRepository; 19 | 20 | @Override 21 | public Optional> findAllPermissionsByUsername(String username) { 22 | log.info("Finding permissions by username {}", username); 23 | return userPermissionRepository.findUserPermissionByUsername(username); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /microservices/microservices-demo/elastic-query-service/src/main/java/com/microservices/demo/elastic/query/service/util/Constants.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.elastic.query.service.util; 2 | 3 | public class Constants { 4 | public static final String NA = "N/A"; 5 | 6 | public static final String CORRELATION_ID_HEADER = "X-Correlation-ID"; 7 | public static final String CORRELATION_ID_KEY = "correlationID"; 8 | } 9 | -------------------------------------------------------------------------------- /microservices/microservices-demo/elastic-query-service/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: elastic-query-service 4 | profiles: 5 | active: elastic_query 6 | cloud: 7 | config: 8 | name: elastic-query-service,config-client 9 | uri: http://config-server:8888 10 | enabled: true 11 | username: spring_cloud_user 12 | password: spring_cloud_password 13 | config: 14 | import: configserver:http://config-server:8888 15 | 16 | 17 | eureka: 18 | client: 19 | serviceUrl: 20 | defaultZone: http://localhost:8761/eureka/ 21 | instance: 22 | lease-expiration-duration-in-seconds: 5 23 | lease-renewal-interval-in-seconds: 2 -------------------------------------------------------------------------------- /microservices/microservices-demo/elastic-query-service/src/main/resources/banner.txt: -------------------------------------------------------------------------------- 1 | _ _ _ ___ _ _ _ _ ___ 2 | /_\ | | (_) / __| /_\ | \| | | | |_ _| 3 | / _ \ | | | | | (__ / _ \ | .` | | |__ | | 4 | /_/ \_\ |_| |_| \___| /_/ \_\ |_|\_| |____| |___| 5 | 6 | ${application.title} ${application.version} 7 | Powered by Spring Boot ${spring-boot.version} -------------------------------------------------------------------------------- /microservices/microservices-demo/elastic-query-service/src/main/resources/init-data.sql: -------------------------------------------------------------------------------- 1 | CREATE EXTENSION IF NOT EXISTS "uuid-ossp"; 2 | 3 | 4 | INSERT INTO public.users( 5 | id, username, firstname, lastname) 6 | VALUES ('1273a5e2-15b5-4a06-968c-01513aa13be5', 'app_user', 'Standard', 'User'); 7 | INSERT INTO public.users( 8 | id, username, firstname, lastname) 9 | VALUES ('7c60fd48-89be-40c6-8b96-3198b62fd986', 'app_admin', 'Admin', 'User'); 10 | INSERT INTO public.users( 11 | id, username, firstname, lastname) 12 | VALUES ('9308257d-8b85-4b9f-a6a3-53d43d77141a', 'app_super_user', 'Super', 'User'); 13 | 14 | 15 | insert into documents(id, document_id) 16 | values ('c1df7d01-4bd7-40b6-86da-7e2ffabf37f7', 'd2231a41-f22f-4bf6-a2b3-5f6a9a573ce7'); 17 | insert into documents(id, document_id) 18 | values ('f2b2d644-3a08-4acb-ae07-20569f6f2a01', '425ae1dc-45af-4ed0-89bb-bf22d94e47dd'); 19 | insert into documents(id, document_id) 20 | values ('90573d2b-9a5d-409e-bbb6-b94189709a19', '494508cc-0047-4d62-a13e-346b983c3732'); 21 | 22 | insert into user_permissions(user_permission_id, user_id, document_id, permission_type) 23 | values (uuid_generate_v4(),'7c60fd48-89be-40c6-8b96-3198b62fd986', 'c1df7d01-4bd7-40b6-86da-7e2ffabf37f7', 'READ'); 24 | 25 | insert into user_permissions(user_permission_id, user_id, document_id, permission_type) 26 | values (uuid_generate_v4(),'7c60fd48-89be-40c6-8b96-3198b62fd986', 'f2b2d644-3a08-4acb-ae07-20569f6f2a01', 'READ'); 27 | 28 | insert into user_permissions(user_permission_id, user_id, document_id, permission_type) 29 | values (uuid_generate_v4(),'7c60fd48-89be-40c6-8b96-3198b62fd986', '90573d2b-9a5d-409e-bbb6-b94189709a19', 'READ'); 30 | 31 | insert into user_permissions(user_permission_id, user_id, document_id, permission_type) 32 | values (uuid_generate_v4(), '9308257d-8b85-4b9f-a6a3-53d43d77141a', '90573d2b-9a5d-409e-bbb6-b94189709a19', 'READ'); 33 | 34 | insert into user_permissions(user_permission_id, user_id, document_id, permission_type) 35 | values (uuid_generate_v4(), '1273a5e2-15b5-4a06-968c-01513aa13be5', '90573d2b-9a5d-409e-bbb6-b94189709a19', 'READ'); 36 | 37 | 38 | -------------------------------------------------------------------------------- /microservices/microservices-demo/elastic-query-service/src/main/resources/init-schema.sql: -------------------------------------------------------------------------------- 1 | DROP TABLE IF EXISTS public.users CASCADE; 2 | 3 | CREATE TABLE public.users 4 | ( 5 | id uuid NOT NULL, 6 | username character varying COLLATE pg_catalog."default", 7 | firstname character varying COLLATE pg_catalog."default", 8 | lastname character varying COLLATE pg_catalog."default", 9 | CONSTRAINT users_pkey PRIMARY KEY (id) 10 | ) 11 | 12 | TABLESPACE pg_default; 13 | 14 | ALTER TABLE public.users OWNER to postgres; 15 | 16 | DROP TABLE IF EXISTS public.documents CASCADE; 17 | 18 | CREATE TABLE public.documents 19 | ( 20 | id uuid NOT NULL, 21 | document_id character varying COLLATE pg_catalog."default" NOT NULL, 22 | CONSTRAINT documents_pkey PRIMARY KEY (id) 23 | ) 24 | 25 | TABLESPACE pg_default; 26 | 27 | ALTER TABLE public.documents 28 | OWNER to postgres; 29 | 30 | DROP TABLE IF EXISTS public.user_permissions CASCADE; 31 | 32 | CREATE TABLE public.user_permissions 33 | ( 34 | user_id uuid NOT NULL, 35 | document_id uuid NOT NULL, 36 | user_permission_id uuid NOT NULL, 37 | permission_type character varying COLLATE pg_catalog."default", 38 | CONSTRAINT document_fk FOREIGN KEY (document_id) 39 | REFERENCES public.documents (id) MATCH SIMPLE 40 | ON UPDATE NO ACTION 41 | ON DELETE NO ACTION 42 | NOT VALID, 43 | CONSTRAINT user_fk FOREIGN KEY (user_id) 44 | REFERENCES public.users (id) MATCH SIMPLE 45 | ON UPDATE NO ACTION 46 | ON DELETE NO ACTION 47 | ) 48 | 49 | TABLESPACE pg_default; 50 | 51 | ALTER TABLE public.user_permissions 52 | OWNER to postgres; 53 | 54 | CREATE INDEX "fki_USER_FK" 55 | ON public.user_permissions USING btree 56 | (user_id ASC NULLS LAST) 57 | TABLESPACE pg_default; 58 | 59 | CREATE INDEX fki_document_fk 60 | ON public.user_permissions USING btree 61 | (document_id ASC NULLS LAST) 62 | TABLESPACE pg_default; 63 | -------------------------------------------------------------------------------- /microservices/microservices-demo/elastic-query-service/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /microservices/microservices-demo/elastic-query-service/src/test/java/com/microservices/demo/elastic/query/service/ElasticQueryServiceAppTests.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.elastic.query.service; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | public class ElasticQueryServiceAppTests { 8 | 9 | @Test 10 | public void contextLoads() { 11 | } 12 | 13 | 14 | } 15 | -------------------------------------------------------------------------------- /microservices/microservices-demo/elastic-query-web-client-common/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | microservices-demo 7 | com.microservices.demo 8 | 0.0.1-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | elastic-query-web-client-common 13 | 14 | 15 | 16 | org.projectlombok 17 | lombok 18 | 19 | 20 | org.springframework 21 | spring-context 22 | 23 | 24 | org.springframework 25 | spring-web 26 | 27 | 28 | org.springframework.security 29 | spring-security-core 30 | 31 | 32 | org.slf4j 33 | slf4j-api 34 | 35 | 36 | org.springframework.boot 37 | spring-boot-starter-validation 38 | 39 | 40 | com.microservices.demo 41 | elastic-model 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /microservices/microservices-demo/elastic-query-web-client-common/src/main/java/com/microservices/demo/elastic/query/web/client/common/exception/ElasticQueryWebClientException.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.elastic.query.web.client.common.exception; 2 | 3 | public class ElasticQueryWebClientException extends RuntimeException { 4 | public ElasticQueryWebClientException(String message) { 5 | super(message); 6 | } 7 | public ElasticQueryWebClientException(String message, Throwable cause) { 8 | super(message, cause); 9 | } 10 | public ElasticQueryWebClientException() { 11 | super(); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /microservices/microservices-demo/elastic-query-web-client-common/src/main/java/com/microservices/demo/elastic/query/web/client/common/model/ElasticQueryWebClientRequestModel.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.elastic.query.web.client.common.model; 2 | 3 | import com.microservices.demo.elastic.model.index.model.FinanceAvroDTO; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Builder; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | import javax.validation.constraints.NotNull; 10 | 11 | @Data 12 | @Builder 13 | @NoArgsConstructor 14 | @AllArgsConstructor 15 | public class ElasticQueryWebClientRequestModel { 16 | 17 | private String id; 18 | @NotNull 19 | private FinanceAvroDTO shareData; 20 | } 21 | -------------------------------------------------------------------------------- /microservices/microservices-demo/elastic-query-web-client-common/src/main/java/com/microservices/demo/elastic/query/web/client/common/model/ElasticQueryWebClientResponseModel.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.elastic.query.web.client.common.model; 2 | 3 | import com.microservices.demo.elastic.model.index.model.FinanceAvroDTO; 4 | import lombok.*; 5 | 6 | import java.time.ZonedDateTime; 7 | import java.time.format.DateTimeFormatter; 8 | 9 | @Setter 10 | @Getter 11 | @Builder 12 | @NoArgsConstructor 13 | @AllArgsConstructor 14 | public class ElasticQueryWebClientResponseModel { 15 | 16 | private String id; 17 | 18 | private FinanceAvroDTO shareData; 19 | private ZonedDateTime createdAt; 20 | 21 | public String getCreatedAt() { 22 | return DateTimeFormatter.ofPattern("dd/MM/yyyy - HH:mm").format(createdAt); 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /microservices/microservices-demo/elastic-query-web-client-reactive/src/main/java/com/microservices/demo/reactive/elastic/query/web/client/ReactiveElasticQueryWebClientApplication.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.reactive.elastic.query.web.client; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.context.annotation.ComponentScan; 6 | 7 | @SpringBootApplication 8 | @ComponentScan(basePackages = {"com.microservices.demo"}) 9 | public class ReactiveElasticQueryWebClientApplication { 10 | public static void main(String[] args) { 11 | SpringApplication.run(ReactiveElasticQueryWebClientApplication.class, args); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /microservices/microservices-demo/elastic-query-web-client-reactive/src/main/java/com/microservices/demo/reactive/elastic/query/web/client/config/WebClientConfig.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.reactive.elastic.query.web.client.config; 2 | 3 | import com.microservices.demo.config.ElasticQueryWebClientConfigData; 4 | import io.netty.channel.ChannelOption; 5 | import io.netty.handler.timeout.ReadTimeoutHandler; 6 | import io.netty.handler.timeout.WriteTimeoutHandler; 7 | import org.springframework.context.annotation.Bean; 8 | import org.springframework.context.annotation.Configuration; 9 | import org.springframework.http.HttpHeaders; 10 | import org.springframework.http.client.reactive.ReactorClientHttpConnector; 11 | import org.springframework.web.reactive.function.client.WebClient; 12 | import reactor.netty.http.client.HttpClient; 13 | 14 | import java.util.concurrent.TimeUnit; 15 | 16 | @Configuration 17 | public class WebClientConfig { 18 | private final ElasticQueryWebClientConfigData.WebClient webClientConfig; 19 | 20 | public WebClientConfig(ElasticQueryWebClientConfigData clientConfigData) { 21 | this.webClientConfig = clientConfigData.getWebClient(); 22 | } 23 | @Bean("webClient") 24 | WebClient webClient() { 25 | return WebClient.builder() 26 | .baseUrl(webClientConfig.getBaseUrl()) 27 | .defaultHeader(HttpHeaders.CONTENT_TYPE, webClientConfig.getContentType()) 28 | .clientConnector(new ReactorClientHttpConnector(getHttpClient())) 29 | .codecs(configurer -> configurer 30 | .defaultCodecs() 31 | .maxInMemorySize(webClientConfig.getMaxInMemorySize())) 32 | .build(); 33 | } 34 | 35 | private HttpClient getHttpClient() { 36 | return HttpClient.create() 37 | .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, webClientConfig.getConnectTimeoutMs()) 38 | .doOnConnected(connection -> { 39 | connection.addHandlerLast(new ReadTimeoutHandler(webClientConfig.getReadTimeoutMs(), 40 | TimeUnit.MILLISECONDS)); 41 | connection.addHandlerLast(new WriteTimeoutHandler(webClientConfig.getWriteTimeoutMs(), 42 | TimeUnit.MILLISECONDS)); 43 | }); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /microservices/microservices-demo/elastic-query-web-client-reactive/src/main/java/com/microservices/demo/reactive/elastic/query/web/client/config/WebSecurityConfig.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.reactive.elastic.query.web.client.config; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.security.config.web.server.ServerHttpSecurity; 6 | import org.springframework.security.web.server.SecurityWebFilterChain; 7 | 8 | @Configuration 9 | public class WebSecurityConfig { 10 | 11 | @Bean 12 | public SecurityWebFilterChain webFluxSecurityConfig(ServerHttpSecurity http) { 13 | http.authorizeExchange() 14 | .anyExchange() 15 | .permitAll(); 16 | http.csrf().disable(); 17 | return http.build(); 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /microservices/microservices-demo/elastic-query-web-client-reactive/src/main/java/com/microservices/demo/reactive/elastic/query/web/client/service/ElasticQueryWebClient.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.reactive.elastic.query.web.client.service; 2 | 3 | import com.microservices.demo.elastic.query.web.client.common.model.ElasticQueryWebClientRequestModel; 4 | import com.microservices.demo.elastic.query.web.client.common.model.ElasticQueryWebClientResponseModel; 5 | import reactor.core.publisher.Flux; 6 | 7 | public interface ElasticQueryWebClient { 8 | 9 | Flux getDataByText(ElasticQueryWebClientRequestModel request); 10 | } 11 | -------------------------------------------------------------------------------- /microservices/microservices-demo/elastic-query-web-client-reactive/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: reactive-elastic-query-web-client 4 | profiles: 5 | active: reactive_elastic_query_web 6 | cloud: 7 | config: 8 | name: reactive-elastic-query-web-client,config-client 9 | uri: http://config-server:8888 10 | enabled: true 11 | username: spring_cloud_user 12 | password: spring_cloud_password 13 | config: 14 | import: configserver:http://config-server:8888 15 | 16 | -------------------------------------------------------------------------------- /microservices/microservices-demo/elastic-query-web-client-reactive/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /microservices/microservices-demo/elastic-query-web-client-reactive/src/main/resources/templates/error.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 |

Query Client

5 |
6 |

An error occurred

7 |
    8 |
  • 9 |
  • 10 |
11 | Main page 12 |
13 |
14 | 15 |
16 | -------------------------------------------------------------------------------- /microservices/microservices-demo/elastic-query-web-client-reactive/src/main/resources/templates/footer.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /microservices/microservices-demo/elastic-query-web-client-reactive/src/main/resources/templates/header.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Query Client 5 | 6 | 7 | 8 | 9 | 10 | 11 | Twitter Search Engine 12 | 13 | 14 | 15 | 16 | 30 | 31 | -------------------------------------------------------------------------------- /microservices/microservices-demo/elastic-query-web-client-reactive/src/main/resources/templates/home.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 |

Query Client

5 |
6 |
7 |
8 | 9 | 10 |
11 | 12 |
13 |
14 |
15 |

16 | 17 |

18 |
19 |

Search results for ''

20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 |
IDNameValueTime
38 |
39 |
40 | 41 |
42 |
43 |
44 | 45 |
46 | 47 | -------------------------------------------------------------------------------- /microservices/microservices-demo/elastic-query-web-client-reactive/src/main/resources/templates/index.html: -------------------------------------------------------------------------------- 1 |
2 | 3 | 8 | 9 |
10 | 11 | 12 | -------------------------------------------------------------------------------- /microservices/microservices-demo/elastic-query-web-client-reactive/src/test/java/com/microservices/demo/reactive/elastic/query/web/client/ReactiveElasticQueryWebClientApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.reactive.elastic.query.web.client; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | public class ReactiveElasticQueryWebClientApplicationTests { 8 | 9 | @Test 10 | public void contextLoads() { 11 | } 12 | 13 | 14 | } 15 | -------------------------------------------------------------------------------- /microservices/microservices-demo/elastic-query-web-client/src/main/java/com/microservices/demo/elastic/query/web/client/ElasticQueryWebClientApp.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.elastic.query.web.client; 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.context.annotation.ComponentScan; 7 | 8 | @EnableDiscoveryClient 9 | @SpringBootApplication 10 | @ComponentScan(basePackages = "com.microservices.demo") 11 | public class ElasticQueryWebClientApp { 12 | 13 | public static void main(String[] args) { 14 | SpringApplication.run(ElasticQueryWebClientApp.class, args); 15 | } 16 | 17 | 18 | } 19 | -------------------------------------------------------------------------------- /microservices/microservices-demo/elastic-query-web-client/src/main/java/com/microservices/demo/elastic/query/web/client/model/ElasticQueryWebClientAnalyticsResponseModel.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.elastic.query.web.client.model; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | @Data 9 | @Builder 10 | @NoArgsConstructor 11 | @AllArgsConstructor 12 | public class ElasticQueryWebClientAnalyticsResponseModel { 13 | 14 | private String queryResponseModels; 15 | private String shareVolume; 16 | 17 | } 18 | -------------------------------------------------------------------------------- /microservices/microservices-demo/elastic-query-web-client/src/main/java/com/microservices/demo/elastic/query/web/client/model/LiveShareResponse.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.elastic.query.web.client.model; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | @Data 9 | @Builder 10 | @NoArgsConstructor 11 | @AllArgsConstructor 12 | public class LiveShareResponse { 13 | private String id; 14 | private String description; 15 | private String last; 16 | private String createdAt; 17 | 18 | } 19 | -------------------------------------------------------------------------------- /microservices/microservices-demo/elastic-query-web-client/src/main/java/com/microservices/demo/elastic/query/web/client/model/LiveValuesResponse.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.elastic.query.web.client.model; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | import java.math.BigDecimal; 9 | import java.util.Map; 10 | 11 | @Data 12 | @Builder 13 | @NoArgsConstructor 14 | @AllArgsConstructor 15 | public class LiveValuesResponse { 16 | Map liveValues; 17 | } 18 | -------------------------------------------------------------------------------- /microservices/microservices-demo/elastic-query-web-client/src/main/java/com/microservices/demo/elastic/query/web/client/service/ElasticQueryWebClientService.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.elastic.query.web.client.service; 2 | 3 | 4 | import com.microservices.demo.elastic.query.web.client.common.model.ElasticQueryWebClientRequestModel; 5 | import com.microservices.demo.elastic.query.web.client.model.ElasticQueryWebClientAnalyticsResponseModel; 6 | import com.microservices.demo.elastic.query.web.client.model.LiveValuesResponse; 7 | 8 | import java.util.List; 9 | 10 | public interface ElasticQueryWebClientService { 11 | ElasticQueryWebClientAnalyticsResponseModel getShareByC(ElasticQueryWebClientRequestModel model); 12 | 13 | LiveValuesResponse getLiveLiveValues(List shareList); 14 | } 15 | -------------------------------------------------------------------------------- /microservices/microservices-demo/elastic-query-web-client/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: elastic-query-web-client 4 | profiles: 5 | active: elastic_query_web 6 | cloud: 7 | config: 8 | name: elastic-query-web-client,config-client 9 | uri: http://config-server:8888 10 | enabled: true 11 | username: spring_cloud_user 12 | password: spring_cloud_password 13 | config: 14 | import: configserver:http://config-server:8888 15 | 16 | 17 | 18 | eureka: 19 | client: 20 | serviceUrl: 21 | defaultZone: http://localhost:8761/eureka/ 22 | instance: 23 | lease-expiration-duration-in-seconds: 5 24 | lease-renewal-interval-in-seconds: 2 -------------------------------------------------------------------------------- /microservices/microservices-demo/elastic-query-web-client/src/main/resources/banner.txt: -------------------------------------------------------------------------------- 1 | _ _ _ ___ _ _ _ _ ___ 2 | /_\ | | (_) / __| /_\ | \| | | | |_ _| 3 | / _ \ | | | | | (__ / _ \ | .` | | |__ | | 4 | /_/ \_\ |_| |_| \___| /_/ \_\ |_|\_| |____| |___| 5 | 6 | ${application.title} ${application.version} 7 | Powered by Spring Boot ${spring-boot.version} -------------------------------------------------------------------------------- /microservices/microservices-demo/elastic-query-web-client/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /microservices/microservices-demo/elastic-query-web-client/src/main/resources/templates/error.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 |

Query Client

5 |
6 |

An error occurred

7 |
    8 |
  • 9 |
  • 10 |
11 | Main page 12 |
13 |
14 | 15 |
16 | -------------------------------------------------------------------------------- /microservices/microservices-demo/elastic-query-web-client/src/main/resources/templates/footer.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /microservices/microservices-demo/elastic-query-web-client/src/main/resources/templates/header.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Query Client 5 | 6 | 7 | 8 | 9 | 10 | 11 | Twitter Search Engine 12 | 13 | 14 | 15 | 16 | 42 | 43 | -------------------------------------------------------------------------------- /microservices/microservices-demo/elastic-query-web-client/src/main/resources/templates/index.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 |
5 |

Please login to start searching

6 |
7 | 8 | 11 |
12 | 13 |
14 | 15 | 16 | -------------------------------------------------------------------------------- /microservices/microservices-demo/elastic-query-web-client/src/test/java/com/microservices/demo/elastic/query/web/client/ElasticQueryWebClientAppTests.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.elastic.query.web.client; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class ElasticQueryWebClientAppTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /microservices/microservices-demo/elastic/elastic-config/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | microservices-demo 7 | com.microservices.demo 8 | 0.0.1-SNAPSHOT 9 | ../../pom.xml 10 | 11 | 4.0.0 12 | 13 | elastic-config 14 | 15 | 16 | 17 | com.microservices.demo 18 | app-config-data 19 | 20 | 21 | 22 | org.springframework.boot 23 | spring-boot-starter-data-elasticsearch 24 | 25 | 26 | 27 | org.springframework 28 | spring-web 29 | 30 | 31 | 32 | com.microservices.demo 33 | elastic-index-client 34 | 35 | 36 | 37 | org.elasticsearch 38 | elasticsearch 39 | 40 | 41 | org.elasticsearch.client 42 | elasticsearch-rest-high-level-client 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /microservices/microservices-demo/elastic/elastic-config/src/main/java/com/microservices/demo/elastic/config/ElasticSearchConfig.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.elastic.config; 2 | 3 | import com.microservices.demo.config.ElasticConfigData; 4 | import lombok.RequiredArgsConstructor; 5 | import org.apache.http.HttpHost; 6 | import org.elasticsearch.client.RestClient; 7 | import org.elasticsearch.client.RestHighLevelClient; 8 | import org.springframework.context.annotation.Bean; 9 | import org.springframework.context.annotation.Configuration; 10 | import org.springframework.data.elasticsearch.config.AbstractElasticsearchConfiguration; 11 | import org.springframework.data.elasticsearch.core.ElasticsearchOperations; 12 | import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate; 13 | import org.springframework.data.elasticsearch.repository.config.EnableElasticsearchRepositories; 14 | import org.springframework.web.util.UriComponents; 15 | import org.springframework.web.util.UriComponentsBuilder; 16 | 17 | import java.util.Objects; 18 | 19 | @Configuration 20 | @RequiredArgsConstructor 21 | @EnableElasticsearchRepositories(basePackages = "com.microservices.demo.elastic") 22 | public class ElasticSearchConfig extends AbstractElasticsearchConfiguration { 23 | private final ElasticConfigData elasticConfigData; 24 | 25 | @Bean 26 | @Override 27 | public RestHighLevelClient elasticsearchClient() { 28 | UriComponents serverUri = UriComponentsBuilder.fromHttpUrl(elasticConfigData.getConnectionUrl()).build(); 29 | return new RestHighLevelClient( 30 | RestClient.builder(new HttpHost( 31 | Objects.requireNonNull(serverUri.getHost()), 32 | serverUri.getPort(), 33 | serverUri.getScheme() 34 | )).setRequestConfigCallback( 35 | requestConfigBuilder -> 36 | requestConfigBuilder 37 | .setConnectTimeout(elasticConfigData.getConnectionTimeout()) 38 | .setSocketTimeout(elasticConfigData.getSocketTimeout()) 39 | ) 40 | ); 41 | } 42 | 43 | @Bean 44 | public ElasticsearchOperations elasticsearchOperations() { 45 | return new ElasticsearchRestTemplate(elasticsearchClient()); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /microservices/microservices-demo/elastic/elastic-index-client/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | microservices-demo 7 | com.microservices.demo 8 | 0.0.1-SNAPSHOT 9 | ../../pom.xml 10 | 11 | 4.0.0 12 | 13 | elastic-index-client 14 | 15 | 16 | 17 | com.microservices.demo 18 | app-config-data 19 | 20 | 21 | 22 | com.microservices.demo 23 | elastic-model 24 | 25 | 26 | 27 | org.springframework.boot 28 | spring-boot-starter-data-elasticsearch 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /microservices/microservices-demo/elastic/elastic-index-client/src/main/java/com/microservices/demo/elastic/index/client/repository/FinanceElasticsearchIndexRepository.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.elastic.index.client.repository; 2 | 3 | import com.microservices.demo.elastic.model.index.impl.FinanceIndexModel; 4 | import org.springframework.data.elasticsearch.repository.ElasticsearchRepository; 5 | import org.springframework.stereotype.Repository; 6 | 7 | @Repository 8 | public interface FinanceElasticsearchIndexRepository extends ElasticsearchRepository { 9 | } 10 | -------------------------------------------------------------------------------- /microservices/microservices-demo/elastic/elastic-index-client/src/main/java/com/microservices/demo/elastic/index/client/service/ElasticIndexClient.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.elastic.index.client.service; 2 | 3 | import com.microservices.demo.elastic.model.index.IndexModel; 4 | 5 | import java.util.List; 6 | 7 | public interface ElasticIndexClient{ 8 | List save(List documents); 9 | } 10 | -------------------------------------------------------------------------------- /microservices/microservices-demo/elastic/elastic-index-client/src/main/java/com/microservices/demo/elastic/index/client/service/impl/FinanceElasticIndexClient.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.elastic.index.client.service.impl; 2 | 3 | import com.microservices.demo.config.ElasticConfigData; 4 | import com.microservices.demo.elastic.index.client.util.ElasticIndexUtil; 5 | import com.microservices.demo.elastic.index.client.service.ElasticIndexClient; 6 | import com.microservices.demo.elastic.model.index.impl.FinanceIndexModel; 7 | import lombok.RequiredArgsConstructor; 8 | import lombok.extern.log4j.Log4j2; 9 | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; 10 | import org.springframework.data.elasticsearch.core.ElasticsearchOperations; 11 | import org.springframework.data.elasticsearch.core.IndexedObjectInformation; 12 | import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates; 13 | import org.springframework.stereotype.Service; 14 | 15 | import java.util.List; 16 | 17 | @Service 18 | @Log4j2 19 | @RequiredArgsConstructor 20 | @ConditionalOnProperty(name = "elastic-config.is-repository", havingValue = "false") 21 | public class FinanceElasticIndexClient implements ElasticIndexClient { 22 | 23 | private final ElasticConfigData elasticConfigData; 24 | private final ElasticsearchOperations elasticsearchOperations; 25 | private final ElasticIndexUtil elasticIndexUtil; 26 | 27 | 28 | @Override 29 | public List save(List documents) { 30 | var indexQueries = elasticIndexUtil.geIndexQueries(documents); 31 | List documentIds = elasticsearchOperations.bulkIndex( 32 | indexQueries, 33 | IndexCoordinates.of(elasticConfigData.getIndexName()) 34 | ).stream().map(IndexedObjectInformation::getId).toList(); 35 | 36 | log.info("Saved {} documents", documentIds.size()); 37 | 38 | return documentIds; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /microservices/microservices-demo/elastic/elastic-index-client/src/main/java/com/microservices/demo/elastic/index/client/service/impl/FinanceElasticRepositoryIndexClient.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.elastic.index.client.service.impl; 2 | 3 | import com.microservices.demo.elastic.index.client.repository.FinanceElasticsearchIndexRepository; 4 | import com.microservices.demo.elastic.index.client.service.ElasticIndexClient; 5 | import com.microservices.demo.elastic.model.index.impl.FinanceIndexModel; 6 | import lombok.RequiredArgsConstructor; 7 | import lombok.extern.slf4j.Slf4j; 8 | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; 9 | import org.springframework.stereotype.Service; 10 | 11 | import java.util.List; 12 | 13 | @Slf4j 14 | @Service 15 | @RequiredArgsConstructor 16 | @ConditionalOnProperty(name = "elastic-config.is-repository", havingValue = "true", matchIfMissing = true) 17 | public class FinanceElasticRepositoryIndexClient implements ElasticIndexClient { 18 | 19 | private final FinanceElasticsearchIndexRepository financeElasticsearchIndexRepository; 20 | 21 | @Override 22 | public List save(List documents) { 23 | var savingQueries = (List) financeElasticsearchIndexRepository.saveAll(documents); 24 | var result = savingQueries.stream().map(FinanceIndexModel::getId).toList(); 25 | log.info("Saved {} documents", savingQueries.size()); 26 | return result; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /microservices/microservices-demo/elastic/elastic-index-client/src/main/java/com/microservices/demo/elastic/index/client/util/ElasticIndexUtil.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.elastic.index.client.util; 2 | 3 | import com.microservices.demo.elastic.model.index.IndexModel; 4 | import org.springframework.data.elasticsearch.core.query.IndexQuery; 5 | import org.springframework.data.elasticsearch.core.query.IndexQueryBuilder; 6 | import org.springframework.stereotype.Component; 7 | 8 | import java.util.List; 9 | 10 | @Component 11 | public class ElasticIndexUtil { 12 | 13 | public List geIndexQueries(List documents) { 14 | return documents.stream() 15 | .map(document -> new IndexQueryBuilder() 16 | .withId(document.getId()) 17 | .withObject(document) 18 | .build()) 19 | .toList(); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /microservices/microservices-demo/elastic/elastic-model/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | microservices-demo 7 | com.microservices.demo 8 | 0.0.1-SNAPSHOT 9 | ../../pom.xml 10 | 11 | 4.0.0 12 | 13 | elastic-model 14 | 15 | 16 | 17 | 18 | org.springframework.boot 19 | spring-boot-starter-data-elasticsearch 20 | 21 | 22 | org.projectlombok 23 | lombok 24 | compile 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /microservices/microservices-demo/elastic/elastic-model/src/main/java/com/microservices/demo/elastic/model/index/IndexModel.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.elastic.model.index; 2 | 3 | public interface IndexModel { 4 | String getId(); 5 | } 6 | -------------------------------------------------------------------------------- /microservices/microservices-demo/elastic/elastic-model/src/main/java/com/microservices/demo/elastic/model/index/impl/FinanceIndexModel.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.elastic.model.index.impl; 2 | 3 | import com.fasterxml.jackson.annotation.JsonFormat; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import com.microservices.demo.elastic.model.index.IndexModel; 6 | import com.microservices.demo.elastic.model.index.model.FinanceAvroDTO; 7 | import lombok.Builder; 8 | import lombok.Data; 9 | import org.springframework.data.elasticsearch.annotations.DateFormat; 10 | import org.springframework.data.elasticsearch.annotations.Document; 11 | import org.springframework.data.elasticsearch.annotations.Field; 12 | import org.springframework.data.elasticsearch.annotations.FieldType; 13 | 14 | import java.time.ZonedDateTime; 15 | 16 | @Data 17 | @Builder 18 | @Document(indexName = "#{@elasticConfigData.indexName}") 19 | public class FinanceIndexModel implements IndexModel { 20 | 21 | @JsonProperty 22 | private String id; 23 | 24 | @JsonProperty 25 | private FinanceAvroDTO shareData; 26 | 27 | @Field(type = FieldType.Date, format = DateFormat.custom, pattern = "uuuu-MM-dd'T'HH:mm:ssZZ") 28 | @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "uuuu-MM-dd'T'HH:mm:ssZZ") 29 | @JsonProperty 30 | private ZonedDateTime createdAt; 31 | 32 | public FinanceAvroDTO getShareData() { 33 | return shareData; 34 | } 35 | 36 | public void setShareData(FinanceAvroDTO shareData) { 37 | this.shareData = shareData; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /microservices/microservices-demo/elastic/elastic-model/src/main/java/com/microservices/demo/elastic/model/index/model/FinanceAvroDTO.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.elastic.model.index.model; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | @Data 9 | @NoArgsConstructor 10 | @AllArgsConstructor 11 | @Builder 12 | public class FinanceAvroDTO { 13 | private String dailyChangePercentage; 14 | private String dailyChange; 15 | private String c; 16 | private String last; 17 | private String dailyVolume; 18 | private String previousDayClose; 19 | private String description; 20 | } 21 | -------------------------------------------------------------------------------- /microservices/microservices-demo/elastic/elastic-query-client/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | microservices-demo 7 | com.microservices.demo 8 | 0.0.1-SNAPSHOT 9 | ../../pom.xml 10 | 11 | 4.0.0 12 | 13 | elastic-query-client 14 | 15 | 16 | 17 | com.microservices.demo 18 | app-config-data 19 | 20 | 21 | 22 | com.microservices.demo 23 | elastic-config 24 | 25 | 26 | 27 | com.microservices.demo 28 | elastic-model 29 | 30 | 31 | 32 | 33 | com.microservices.demo 34 | common-util 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /microservices/microservices-demo/elastic/elastic-query-client/src/main/java/com/microservices/demo/elastic/query/client/exception/ElasticQueryClientException.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.elastic.query.client.exception; 2 | 3 | public class ElasticQueryClientException extends RuntimeException { 4 | public ElasticQueryClientException(String message) { 5 | super(message); 6 | } 7 | public ElasticQueryClientException(String message, Throwable cause) { 8 | super(message, cause); 9 | } 10 | public ElasticQueryClientException() { 11 | super(); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /microservices/microservices-demo/elastic/elastic-query-client/src/main/java/com/microservices/demo/elastic/query/client/repository/FinanceElasticSearchQueryRepository.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.elastic.query.client.repository; 2 | 3 | import com.microservices.demo.elastic.model.index.impl.FinanceIndexModel; 4 | import org.springframework.data.elasticsearch.repository.ElasticsearchRepository; 5 | import org.springframework.stereotype.Repository; 6 | 7 | import java.util.List; 8 | 9 | @Repository 10 | public interface FinanceElasticSearchQueryRepository extends ElasticsearchRepository { 11 | List findByShareDataCIn(String c); 12 | 13 | } 14 | -------------------------------------------------------------------------------- /microservices/microservices-demo/elastic/elastic-query-client/src/main/java/com/microservices/demo/elastic/query/client/service/ElasticQueryClient.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.elastic.query.client.service; 2 | 3 | import com.microservices.demo.elastic.model.index.IndexModel; 4 | 5 | import java.util.List; 6 | 7 | public interface ElasticQueryClient { 8 | 9 | T getIndexModelById(String id); 10 | List getIndexModelByFieldShareData(String shareData); 11 | List getIndexModelForAll(); 12 | 13 | } 14 | -------------------------------------------------------------------------------- /microservices/microservices-demo/elastic/elastic-query-client/src/main/java/com/microservices/demo/elastic/query/client/service/impl/FinanceElasticRepositoryQueryClient.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.elastic.query.client.service.impl; 2 | 3 | import com.microservices.demo.common.util.CollectionsUtil; 4 | import com.microservices.demo.elastic.model.index.impl.FinanceIndexModel; 5 | import com.microservices.demo.elastic.query.client.repository.FinanceElasticSearchQueryRepository; 6 | import com.microservices.demo.elastic.query.client.service.ElasticQueryClient; 7 | import lombok.RequiredArgsConstructor; 8 | import lombok.extern.slf4j.Slf4j; 9 | import org.springframework.context.annotation.Primary; 10 | import org.springframework.stereotype.Service; 11 | 12 | import java.util.List; 13 | 14 | @Slf4j 15 | @Service 16 | @Primary 17 | @RequiredArgsConstructor 18 | public class FinanceElasticRepositoryQueryClient implements ElasticQueryClient { 19 | 20 | private final FinanceElasticSearchQueryRepository financeElasticSearchQueryRepository; 21 | 22 | @Override 23 | public FinanceIndexModel getIndexModelById(String id) { 24 | return financeElasticSearchQueryRepository.findById(id) 25 | .orElseThrow(() -> new RuntimeException("No result found for id: " + id)); 26 | } 27 | 28 | @Override 29 | public List getIndexModelByFieldShareData(String field) { 30 | log.info("Elasticsearch query for documents with share data: ".concat(field)); 31 | return financeElasticSearchQueryRepository.findByShareDataCIn(field); 32 | } 33 | 34 | @Override 35 | public List getIndexModelForAll() { 36 | return CollectionsUtil.getInstance() 37 | .getListFromIterable(financeElasticSearchQueryRepository.findAll()); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /microservices/microservices-demo/elastic/elastic-query-client/src/main/java/com/microservices/demo/elastic/query/client/util/ElasticQueryUtil.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.elastic.query.client.util; 2 | 3 | import com.microservices.demo.elastic.model.index.IndexModel; 4 | import org.elasticsearch.index.query.BoolQueryBuilder; 5 | import org.elasticsearch.index.query.QueryBuilders; 6 | import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder; 7 | import org.springframework.data.elasticsearch.core.query.Query; 8 | import org.springframework.stereotype.Component; 9 | 10 | import java.util.Collections; 11 | 12 | @Component 13 | public class ElasticQueryUtil { 14 | 15 | public Query getSearchQueryById(String id){ 16 | return new NativeSearchQueryBuilder() 17 | .withIds(Collections.singleton(id)) 18 | .build(); 19 | } 20 | 21 | public Query getSearchQueryByFieldShareData(String field, String value){ 22 | return new NativeSearchQueryBuilder() 23 | .withQuery(new BoolQueryBuilder() 24 | .must(QueryBuilders.matchQuery(field, value))) 25 | .build(); 26 | } 27 | 28 | public Query getSearchQueryForAll(){ 29 | return new NativeSearchQueryBuilder() 30 | .withQuery(QueryBuilders.matchAllQuery()) 31 | .build(); 32 | } 33 | 34 | 35 | } 36 | -------------------------------------------------------------------------------- /microservices/microservices-demo/elastic/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | microservices-demo 7 | com.microservices.demo 8 | 0.0.1-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | elastic 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /microservices/microservices-demo/finance-stream-service/src/main/java/com/finance/stream/api/FinanceStreamApp.java: -------------------------------------------------------------------------------- 1 | package com.finance.stream.api; 2 | 3 | import com.finance.stream.api.init.StreamInitializer; 4 | import lombok.RequiredArgsConstructor; 5 | import lombok.extern.slf4j.Slf4j; 6 | import org.springframework.boot.CommandLineRunner; 7 | import org.springframework.boot.SpringApplication; 8 | import org.springframework.boot.autoconfigure.SpringBootApplication; 9 | import org.springframework.cloud.client.discovery.EnableDiscoveryClient; 10 | import org.springframework.cloud.openfeign.EnableFeignClients; 11 | import org.springframework.context.annotation.ComponentScan; 12 | import org.springframework.scheduling.annotation.EnableScheduling; 13 | 14 | @Slf4j 15 | @EnableScheduling 16 | @EnableFeignClients 17 | @EnableDiscoveryClient 18 | @SpringBootApplication 19 | @ComponentScan(basePackages = {"com.microservices.demo", 20 | "com.finance.stream.api"}) 21 | @RequiredArgsConstructor 22 | public class FinanceStreamApp implements CommandLineRunner { 23 | public static void main(String[] args) { 24 | SpringApplication.run(FinanceStreamApp.class, args); 25 | } 26 | 27 | private final StreamInitializer streamInitializer; 28 | @Override 29 | public void run(String... args) { 30 | log.info("Initializing Kafka Stream"); 31 | streamInitializer.init(); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /microservices/microservices-demo/finance-stream-service/src/main/java/com/finance/stream/api/client/FinanceService.java: -------------------------------------------------------------------------------- 1 | package com.finance.stream.api.client; 2 | 3 | import com.finance.stream.api.dto.FinanceApiDTO; 4 | import org.springframework.cloud.openfeign.FeignClient; 5 | import org.springframework.web.bind.annotation.GetMapping; 6 | import org.springframework.web.bind.annotation.RequestParam; 7 | 8 | import java.util.List; 9 | 10 | @FeignClient(value = "finance-stream-service", 11 | url = "https://www.isyatirim.com.tr/_layouts/15/Isyatirim.Website/Common/Data.aspx/OneEndeks?endeks=") 12 | public interface FinanceService { 13 | 14 | @GetMapping 15 | List getBISTInformation(@RequestParam String endeks); 16 | } 17 | -------------------------------------------------------------------------------- /microservices/microservices-demo/finance-stream-service/src/main/java/com/finance/stream/api/converter/FinanceToAvroConverter.java: -------------------------------------------------------------------------------- 1 | package com.finance.stream.api.converter; 2 | 3 | import com.finance.stream.api.dto.FinanceApiDTO; 4 | import com.microservices.demo.kafka.avro.model.FinanceAvroModel; 5 | import com.microservices.demo.kafka.avro.model.Share; 6 | import org.springframework.stereotype.Component; 7 | 8 | import java.util.Date; 9 | import java.util.UUID; 10 | 11 | @Component 12 | public class FinanceToAvroConverter { 13 | 14 | public FinanceAvroModel getFinanceAvroModel(FinanceApiDTO finance) { 15 | return FinanceAvroModel.newBuilder() 16 | .setId(UUID.randomUUID().toString()) 17 | .setCreatedAt(new Date().getTime()) 18 | .setShareData(Share.newBuilder() 19 | .setC(finance.c().substring(0, finance.c().indexOf("."))) 20 | .setDailyChange(finance.dailyChange()) 21 | .setDescription(finance.description()) 22 | .setLast(finance.last()) 23 | .setDailyChangePercentage(finance.dailyChangePercentage()) 24 | .setDailyVolume(finance.dailyVolume()) 25 | .setPreviousDayClose(finance.previousDayClose()) 26 | .build()) 27 | .build(); 28 | } 29 | 30 | 31 | } 32 | -------------------------------------------------------------------------------- /microservices/microservices-demo/finance-stream-service/src/main/java/com/finance/stream/api/dto/FinanceApiDTO.java: -------------------------------------------------------------------------------- 1 | package com.finance.stream.api.dto; 2 | 3 | 4 | import lombok.Builder; 5 | 6 | @Builder 7 | public record FinanceApiDTO( 8 | String dailyChangePercentage, 9 | String dailyChange, 10 | String c, 11 | String last, 12 | String dailyVolume, 13 | String previousDayClose, 14 | String description) { 15 | 16 | } 17 | -------------------------------------------------------------------------------- /microservices/microservices-demo/finance-stream-service/src/main/java/com/finance/stream/api/init/StreamInitializer.java: -------------------------------------------------------------------------------- 1 | package com.finance.stream.api.init; 2 | 3 | public interface StreamInitializer { 4 | void init(); 5 | } 6 | -------------------------------------------------------------------------------- /microservices/microservices-demo/finance-stream-service/src/main/java/com/finance/stream/api/init/impl/KafkaStreamInitializer.java: -------------------------------------------------------------------------------- 1 | package com.finance.stream.api.init.impl; 2 | 3 | import com.finance.stream.api.init.StreamInitializer; 4 | import com.microservices.demo.config.KafkaConfigData; 5 | import com.microservices.demo.kafka.admin.client.KafkaAdminClient; 6 | import lombok.RequiredArgsConstructor; 7 | import lombok.extern.slf4j.Slf4j; 8 | import org.springframework.stereotype.Service; 9 | 10 | @Slf4j 11 | @Service 12 | @RequiredArgsConstructor 13 | public class KafkaStreamInitializer implements StreamInitializer { 14 | 15 | private final KafkaAdminClient kafkaAdminClient; 16 | 17 | @Override 18 | public void init() { 19 | log.info("Initializing Kafka Stream"); 20 | kafkaAdminClient.createTopics(); 21 | kafkaAdminClient.checkSchemaRegistry(); 22 | log.info("Kafka Stream initialized"); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /microservices/microservices-demo/finance-stream-service/src/main/java/com/finance/stream/api/scheduler/FinanceStreamScheduler.java: -------------------------------------------------------------------------------- 1 | package com.finance.stream.api.scheduler; 2 | 3 | import com.finance.stream.api.client.FinanceService; 4 | import com.finance.stream.api.service.ProcessData; 5 | import com.microservices.demo.config.FinanceDataStreamConfig; 6 | import lombok.RequiredArgsConstructor; 7 | import lombok.extern.slf4j.Slf4j; 8 | import org.springframework.scheduling.annotation.Scheduled; 9 | import org.springframework.stereotype.Component; 10 | 11 | @Slf4j 12 | @Component 13 | @RequiredArgsConstructor 14 | public class FinanceStreamScheduler { 15 | private final FinanceService financeService; 16 | private final FinanceDataStreamConfig financeDataStreamConfig; 17 | private final ProcessData processData; 18 | 19 | // @Scheduled( cron = "0/20 * 10-18 * * MON-FRI", 20 | // zone = "Europe/Istanbul") 21 | @Scheduled(fixedDelay = 20000) 22 | public void getBistInformation() { 23 | financeDataStreamConfig 24 | .getShareList() 25 | .forEach(bist -> 26 | { 27 | var endeksUrl = bist.concat(financeDataStreamConfig.getUrlAppend()); 28 | var bistShare = financeService.getBISTInformation(endeksUrl); 29 | 30 | if (bistShare.isEmpty()){ 31 | log.error("Error on getting information... Try later !"); 32 | throw new RuntimeException("Error on getting information... Try later !"); 33 | } 34 | 35 | try { 36 | processData.processData(bistShare); 37 | Thread.sleep(500); 38 | } catch (Exception e) { 39 | log.error("Error in interrupted or processing data with kafka: {}", e.getMessage()); 40 | } 41 | }); 42 | 43 | } 44 | 45 | } 46 | 47 | -------------------------------------------------------------------------------- /microservices/microservices-demo/finance-stream-service/src/main/java/com/finance/stream/api/service/ProcessData.java: -------------------------------------------------------------------------------- 1 | package com.finance.stream.api.service; 2 | 3 | import com.finance.stream.api.dto.FinanceApiDTO; 4 | 5 | import java.util.List; 6 | 7 | public interface ProcessData { 8 | void processData(List financeApiDTOs); 9 | } 10 | -------------------------------------------------------------------------------- /microservices/microservices-demo/finance-stream-service/src/main/java/com/finance/stream/api/service/impl/KafkaStreamProcessor.java: -------------------------------------------------------------------------------- 1 | package com.finance.stream.api.service.impl; 2 | 3 | import com.finance.stream.api.converter.FinanceToAvroConverter; 4 | import com.finance.stream.api.dto.FinanceApiDTO; 5 | import com.finance.stream.api.service.ProcessData; 6 | import com.microservices.demo.config.KafkaConfigData; 7 | import com.microservices.demo.kafka.avro.model.FinanceAvroModel; 8 | import com.microservices.demo.kafka.producer.config.service.KafkaProducer; 9 | import lombok.RequiredArgsConstructor; 10 | import lombok.extern.slf4j.Slf4j; 11 | import org.springframework.stereotype.Service; 12 | 13 | import java.util.List; 14 | 15 | @Service 16 | @RequiredArgsConstructor 17 | @Slf4j 18 | public class KafkaStreamProcessor implements ProcessData { 19 | 20 | private final KafkaConfigData kafkaConfigData; 21 | private final KafkaProducer kafkaProducer; 22 | private final FinanceToAvroConverter financeToAvroConverter; 23 | 24 | @Override 25 | public void processData(List financeApiDTOs) { 26 | 27 | var financeAvroModel = 28 | financeToAvroConverter.getFinanceAvroModel(financeApiDTOs.get(0)); 29 | 30 | kafkaProducer.send(kafkaConfigData.getTopicName(), financeAvroModel.getId(), financeAvroModel); 31 | 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /microservices/microservices-demo/finance-stream-service/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: finance-stream-service 4 | profiles: 5 | active: finance_stream_service 6 | cloud: 7 | config: 8 | name: finance-stream-service,config-client 9 | uri: http://config-server:8888 10 | enabled: true 11 | username: spring_cloud_user 12 | password: spring_cloud_password 13 | config: 14 | import: configserver:http://config-server:8888 15 | 16 | eureka: 17 | client: 18 | serviceUrl: 19 | defaultZone: http://localhost:8761/eureka/ 20 | instance: 21 | lease-expiration-duration-in-seconds: 5 22 | lease-renewal-interval-in-seconds: 2 -------------------------------------------------------------------------------- /microservices/microservices-demo/finance-stream-service/src/main/resources/banner.txt: -------------------------------------------------------------------------------- 1 | _ _ _ ___ _ _ _ _ ___ 2 | /_\ | | (_) / __| /_\ | \| | | | |_ _| 3 | / _ \ | | | | | (__ / _ \ | .` | | |__ | | 4 | /_/ \_\ |_| |_| \___| /_/ \_\ |_|\_| |____| |___| 5 | 6 | ${application.title} ${application.version} 7 | Powered by Spring Boot ${spring-boot.version} -------------------------------------------------------------------------------- /microservices/microservices-demo/finance-stream-service/src/main/resources/logback-spring.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /microservices/microservices-demo/finance-stream-service/src/test/java/com/finance/stream/api/FinanceStreamAppTests.java: -------------------------------------------------------------------------------- 1 | package com.finance.stream.api; 2 | 3 | import com.microservices.demo.kafka.admin.client.KafkaAdminClient; 4 | import com.microservices.demo.kafka.avro.model.FinanceAvroModel; 5 | import com.microservices.demo.kafka.avro.model.Share; 6 | import com.microservices.demo.kafka.producer.config.service.KafkaProducer; 7 | import org.junit.jupiter.api.Test; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.boot.test.context.SpringBootTest; 10 | import org.springframework.boot.test.mock.mockito.MockBean; 11 | import org.springframework.kafka.test.context.EmbeddedKafka; 12 | import org.springframework.test.annotation.DirtiesContext; 13 | import org.springframework.test.context.ActiveProfiles; 14 | 15 | import java.util.Date; 16 | 17 | import static org.mockito.Mockito.doNothing; 18 | 19 | @SpringBootTest(classes = {MockSerdeConfig.class}, properties = {"spring.main.allow-bean-definition-overriding=true"}) 20 | @ActiveProfiles("test") 21 | @DirtiesContext 22 | @EmbeddedKafka(partitions = 1, brokerProperties = {"listeners=PLAINTEXT://localhost:9092", "port=9092"}) 23 | class FinanceStreamAppTests { 24 | @Autowired 25 | private KafkaProducer kafkaProducer; 26 | 27 | @MockBean 28 | private KafkaAdminClient kafkaAdminClient; 29 | 30 | @Test 31 | void testKafka() { 32 | 33 | doNothing().when(kafkaAdminClient).checkSchemaRegistry(); 34 | 35 | FinanceAvroModel financeAvroModel = FinanceAvroModel.newBuilder() 36 | .setId("74772abc-0a62-47ca-9210-24437c26a6c1") 37 | .setCreatedAt(new Date().getTime()) 38 | .setShareData(Share.newBuilder() 39 | .setPreviousDayClose("TEST") 40 | .setDailyVolume("TEST") 41 | .setDailyChangePercentage("TEST") 42 | .setLast("TEST") 43 | .setDescription("TEST") 44 | .setDailyChange("TEST") 45 | .setC("TEST") 46 | .build()) 47 | .build(); 48 | kafkaProducer.send("finance-topic", financeAvroModel.getId(), financeAvroModel); 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /microservices/microservices-demo/finance-stream-service/src/test/resources/application-test.yml: -------------------------------------------------------------------------------- 1 | logging: 2 | level: 3 | ROOT: INFO 4 | org.spring.framework.cloud.config: INFO 5 | 6 | spring: 7 | banner: 8 | location: classpath:banner.txt 9 | 10 | finance-share: 11 | share-list: 12 | - SASA 13 | - SISE 14 | - TOASO 15 | - EREGL 16 | - AKBNK 17 | - ARCLK 18 | - ASELS 19 | - BIMAS 20 | - BRMEN 21 | - DENGE 22 | url-append: .E.BIST 23 | 24 | retry-config: 25 | initial-interval-ms: 1000 26 | max-interval-ms: 10000 27 | multiplier: 2.0 28 | max-attempts: 5 29 | sleep-time-ms: 2000 30 | 31 | kafka-config: 32 | bootstrap-servers: localhost:19092, localhost:29092, localhost:39092 33 | schema-registry-url-key: schema.registry.url 34 | schema-registry-url: http://localhost:8081 35 | topic-name: finance-topic 36 | topic-names-to-create: 37 | - finance-topic 38 | num-of-partitions: 3 39 | replication-factor: 3 40 | 41 | 42 | kafka-producer-config: 43 | key-serializer-class: org.apache.kafka.common.serialization.StringSerializer 44 | value-serializer-class: io.confluent.kafka.serializers.KafkaAvroSerializer 45 | compression-type: snappy 46 | acks: all 47 | batch-size: 16384 48 | batch-size-boost-factor: 100 49 | linger-ms: 5 50 | request-timeout-ms: 60000 51 | retry-count: 5 -------------------------------------------------------------------------------- /microservices/microservices-demo/infrastructure/docker-compose/.env: -------------------------------------------------------------------------------- 1 | COMPOSE_PATH_SEPARATOR=: 2 | COMPOSE_FILE=common.yml:kafka_cluster.yml:elastic_cluster.yml:redis_cluster.yml:monitoring.yml:zipkin.yml:keycloak.yml:services.yml 3 | KAFKA_VERSION=5.0.4 4 | ELASTIC_VERSION=7.9.1 5 | ZIPKIN_VERSION=2.22.2 6 | KEYCLOAK_VERSION=11.0.3 7 | REDIS_VERSION=6.0.5 8 | GRAFANA_VERSION=5.4.3 9 | PROMETHEUS_VERSION=v2.19.2 10 | SERVICE_VERSION=0.0.1-SNAPSHOT 11 | GLOBAL_NETWORK=application 12 | GROUP_ID=com.microservices.demo -------------------------------------------------------------------------------- /microservices/microservices-demo/infrastructure/docker-compose/check-config-server-started.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # check-config-server-started.sh 3 | 4 | apt-get update -y 5 | 6 | yes | apt-get install curl 7 | 8 | curlResult=$(curl -s -o /dev/null -I -w "%{http_code}" http://config-server:8888/actuator/health) 9 | 10 | echo "result status code:" "$curlResult" 11 | 12 | while [[ ! $curlResult == "200" ]]; do 13 | >&2 echo "Config server is not up yet!" 14 | sleep 2 15 | curlResult=$(curl -s -o /dev/null -I -w "%{http_code}" http://config-server:8888/actuator/health) 16 | done 17 | 18 | check-keycloak-server-started.sh -------------------------------------------------------------------------------- /microservices/microservices-demo/infrastructure/docker-compose/check-keycloak-server-started.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # check-keycloak-server-started.sh 3 | 4 | curlResult=$(curl -s -o /dev/null -I -w "%{http_code}" http://keycloak:8080/realms/microservices-realm) 5 | 6 | echo "result status code:" "$curlResult" 7 | 8 | while [[ ! $curlResult == "200" ]]; do 9 | >&2 echo "Keycloak server is not up yet!" 10 | sleep 2 11 | curlResult=$(curl -s -o /dev/null -I -w "%{http_code}" http://keycloak:8080/realms/microservices-realm) 12 | done 13 | 14 | /cnb/process/web -------------------------------------------------------------------------------- /microservices/microservices-demo/infrastructure/docker-compose/common.yml: -------------------------------------------------------------------------------- 1 | version: '3.7' 2 | 3 | networks: 4 | application: 5 | driver: bridge -------------------------------------------------------------------------------- /microservices/microservices-demo/infrastructure/docker-compose/config/logback.conf: -------------------------------------------------------------------------------- 1 | input { 2 | file { 3 | path => "/logs/*.log" 4 | codec => "json" 5 | type => "logback" 6 | } 7 | } 8 | 9 | output { 10 | if [type]=="logback" { 11 | elasticsearch { 12 | hosts => [ "http://elastic-1:9200" ] 13 | index => "logback-finance-%{+YYYY.MM.dd}" 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /microservices/microservices-demo/infrastructure/docker-compose/config/prometheus.yml: -------------------------------------------------------------------------------- 1 | scrape_configs: 2 | - job_name: 'prometheus' 3 | scrape_interval: 1m 4 | static_configs: 5 | - targets: ['localhost:9090'] 6 | - job_name: 'grafana' 7 | scrape_interval: 1m 8 | metrics_path: '/metrics' 9 | static_configs: 10 | - targets: ['grafana:3000'] 11 | - job_name: 'gateway-service' 12 | scrape_interval: 1m 13 | metrics_path: '/actuator/metrics' 14 | static_configs: 15 | - targets: ['gateway-service:1111'] 16 | - job_name: 'elastic-query-service-1' 17 | scrape_interval: 1m 18 | metrics_path: 'elastic-query-service/actuator/metrics' 19 | static_configs: 20 | - targets: ['elastic-query-service-1:8183'] 21 | - job_name: 'kafka-streams-service' 22 | scrape_interval: 1m 23 | metrics_path: 'kafka-streams-service/actuator/metrics' 24 | static_configs: 25 | - targets: ['kafka-streams-service:8187'] 26 | - job_name: 'analytics-service' 27 | scrape_interval: 1m 28 | metrics_path: 'analytics-service/actuator/metrics' 29 | static_configs: 30 | - targets: ['analytics-service:8188'] -------------------------------------------------------------------------------- /microservices/microservices-demo/infrastructure/docker-compose/keycloak.yml: -------------------------------------------------------------------------------- 1 | version: '3.7' 2 | services: 3 | 4 | postgres: 5 | image: postgres:latest 6 | restart: always 7 | volumes: 8 | - ./pgdata:/var/lib/postgresql/data 9 | environment: 10 | POSTGRES_DB: keycloak 11 | POSTGRES_USER: keycloak 12 | POSTGRES_PASSWORD: password 13 | ports: 14 | - '5432:5432' 15 | networks: 16 | - ${GLOBAL_NETWORK:-services} 17 | 18 | keycloak: 19 | image: quay.io/keycloak/keycloak:18.0.0 20 | environment: 21 | DB_VENDOR: POSTGRES 22 | DB_ADDR: postgres 23 | DB_SCHEMA: keycloak 24 | DB_DATABASE: keycloak 25 | DB_USER: keycloak 26 | DB_PASSWORD: password 27 | KEYCLOAK_USER: admin 28 | KEYCLOAK_PASSWORD: password 29 | KEYCLOAK_ADMIN_PASSWORD: password 30 | KEYCLOAK_ADMIN: admin 31 | ports: 32 | - "8080:8080" 33 | command: 34 | - start-dev 35 | depends_on: 36 | - postgres 37 | networks: 38 | - ${GLOBAL_NETWORK:-services} -------------------------------------------------------------------------------- /microservices/microservices-demo/infrastructure/docker-compose/monitoring.yml: -------------------------------------------------------------------------------- 1 | version: '3.7' 2 | services: 3 | grafana: 4 | image: grafana/grafana:${GRAFANA_VERSION:-latest} 5 | hostname: grafana 6 | ports: 7 | - "3000:3000" 8 | volumes: 9 | - ./grafana:/var/lib/grafana 10 | environment: 11 | - GF_SECURITY_ADMIN_USER=admin 12 | - GF_SECURITY_ADMIN_PASSWORD=admin 13 | networks: 14 | - ${GLOBAL_NETWORK:-grafana} 15 | prometheus: 16 | image: prom/prometheus:${PROMETHEUS_VERSION:-latest} 17 | hostname: prometheus 18 | ports: 19 | - "9090:9090" 20 | volumes: 21 | - ./config/prometheus.yml:/etc/prometheus/prometheus.yml 22 | - ./prometheus:/prometheus 23 | networks: 24 | - ${GLOBAL_NETWORK:-prometheus} 25 | -------------------------------------------------------------------------------- /microservices/microservices-demo/infrastructure/docker-compose/redis_cluster.yml: -------------------------------------------------------------------------------- 1 | version: '3.7' 2 | services: 3 | redis-master: 4 | image: redis:${REDIS_VERSION:-latest} 5 | hostname: redis 6 | command: ["redis-server", "--appendonly", "yes"] 7 | ports: 8 | - "6379:6379" 9 | networks: 10 | - ${GLOBAL_NETWORK:-redis} 11 | redis-slave: 12 | image: redis:${REDIS_VERSION:-latest} 13 | command: ["redis-server", "--slaveof", "redis-master", "6379"] 14 | ports: 15 | - "6380:6379" 16 | depends_on: 17 | - redis-master 18 | networks: 19 | - ${GLOBAL_NETWORK:-redis} 20 | -------------------------------------------------------------------------------- /microservices/microservices-demo/infrastructure/docker-compose/zipkin.yml: -------------------------------------------------------------------------------- 1 | version: '3.7' 2 | services: 3 | storage: 4 | image: openzipkin/zipkin-mysql:${ZIPKIN_VERSION-latest} 5 | container_name: mysql 6 | networks: 7 | - ${GLOBAL_NETWORK:-zipkin} 8 | zipkin: 9 | image: openzipkin/zipkin:${ZIPKIN_VERSION-latest} 10 | hostname: zipkin 11 | container_name: zipkin 12 | environment: 13 | - STORAGE_TYPE=mysql 14 | - MYSQL_HOST=mysql 15 | - MYSQL_USER=zipkin 16 | - MYSQL_PASS=zipkin 17 | - JAVA_OPTS=-Dlogging.level.zipkin2=DEBUG 18 | - KAFKA_BOOTSTRAP_SERVERS=kafka-broker-1:9092, kafka-broker-2:9092, kafka-broker-3:9092 19 | ports: 20 | - "9411:9411" 21 | depends_on: 22 | - storage 23 | networks: 24 | - ${GLOBAL_NETWORK:-zipkin} 25 | -------------------------------------------------------------------------------- /microservices/microservices-demo/infrastructure/docker-compose/zookeper.yml: -------------------------------------------------------------------------------- 1 | version: '3.7' 2 | services: 3 | zookeeper: 4 | image: confluentinc/cp-zookeeper:${KAFKA_VERSION:-latest} 5 | hostname: zookeeper 6 | ports: 7 | - "2181:2181" 8 | environment: 9 | ZOOKEEPER_CLIENT_PORT: 2181 10 | ZOOKEEPER_TICK_TIME: 2000 11 | ZOOKEEPER_INIT_LIMIT: 5 12 | ZOOKEEPER_SYNC_LIMIT: 2 13 | ZOOKEEPER_SERVER_ID: 1 14 | ZOOKEEPER_SERVERS: zookeeper:2181:3888 15 | KAFKA_OPTS: "-Dzookeeper.4lw.commands.whitelist=ruok" 16 | volumes: 17 | - "./volumes/zookeeper/data:/var/lib/zookeeper/data" 18 | - "./volumes/zookeeper/transactions:/var/lib/zookeeper/log" 19 | networks: 20 | - ${GLOBAL_NETWORK:-kafka} -------------------------------------------------------------------------------- /microservices/microservices-demo/infrastructure/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | microservices-demo 7 | com.microservices.demo 8 | 0.0.1-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | infrastructure 13 | pom 14 | 15 | 16 | -------------------------------------------------------------------------------- /microservices/microservices-demo/kafka-streams-service/src/main/java/com/microservices/demo/kafka/streams/service/Constants.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.kafka.streams.service; 2 | 3 | public class Constants { 4 | public static final String NA = "N/A"; 5 | } 6 | -------------------------------------------------------------------------------- /microservices/microservices-demo/kafka-streams-service/src/main/java/com/microservices/demo/kafka/streams/service/KafkaStreamsServiceApplication.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.kafka.streams.service; 2 | 3 | import com.microservices.demo.kafka.streams.service.init.StreamsInitializer; 4 | import com.microservices.demo.kafka.streams.service.runner.StreamsRunner; 5 | import lombok.RequiredArgsConstructor; 6 | import lombok.extern.slf4j.Slf4j; 7 | import org.springframework.boot.CommandLineRunner; 8 | import org.springframework.boot.SpringApplication; 9 | import org.springframework.boot.autoconfigure.SpringBootApplication; 10 | import org.springframework.cloud.client.discovery.EnableDiscoveryClient; 11 | import org.springframework.context.annotation.ComponentScan; 12 | 13 | @Slf4j 14 | @EnableDiscoveryClient 15 | @SpringBootApplication 16 | @RequiredArgsConstructor 17 | @ComponentScan(basePackages = {"com.microservices.demo"}) 18 | public class KafkaStreamsServiceApplication implements CommandLineRunner { 19 | 20 | 21 | private final StreamsRunner streamsRunner; 22 | 23 | private final StreamsInitializer streamsInitializer; 24 | 25 | 26 | 27 | public static void main(String[] args) { 28 | SpringApplication.run(KafkaStreamsServiceApplication.class, args); 29 | } 30 | 31 | @Override 32 | public void run(String... args) { 33 | log.info("App starts..."); 34 | streamsInitializer.init(); 35 | streamsRunner.start(); 36 | } 37 | 38 | } -------------------------------------------------------------------------------- /microservices/microservices-demo/kafka-streams-service/src/main/java/com/microservices/demo/kafka/streams/service/config/KafkaStreamsConfig.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.kafka.streams.service.config; 2 | 3 | import com.microservices.demo.config.KafkaConfigData; 4 | import com.microservices.demo.config.KafkaStreamsConfigData; 5 | import io.confluent.kafka.serializers.AbstractKafkaSchemaSerDeConfig; 6 | import org.apache.kafka.common.serialization.Serdes; 7 | import org.apache.kafka.streams.StreamsConfig; 8 | import org.springframework.beans.factory.annotation.Qualifier; 9 | import org.springframework.context.annotation.Bean; 10 | import org.springframework.context.annotation.Configuration; 11 | 12 | import java.util.Properties; 13 | 14 | 15 | @Configuration 16 | public class KafkaStreamsConfig { 17 | 18 | private final KafkaConfigData kafkaConfigData; 19 | 20 | private final KafkaStreamsConfigData kafkaStreamsConfigData; 21 | 22 | public KafkaStreamsConfig(KafkaConfigData kafkaConfig, 23 | KafkaStreamsConfigData kafkaStreamsConfig) { 24 | this.kafkaConfigData = kafkaConfig; 25 | this.kafkaStreamsConfigData = kafkaStreamsConfig; 26 | } 27 | 28 | 29 | @Bean 30 | @Qualifier("streamConfiguration") 31 | public Properties streamsConfiguration() { 32 | Properties streamsConfiguration = new Properties(); 33 | streamsConfiguration.put(StreamsConfig.APPLICATION_ID_CONFIG, kafkaStreamsConfigData.getApplicationID()); 34 | streamsConfiguration.put(StreamsConfig.BOOTSTRAP_SERVERS_CONFIG, kafkaConfigData.getBootstrapServers()); 35 | streamsConfiguration.put(AbstractKafkaSchemaSerDeConfig.SCHEMA_REGISTRY_URL_CONFIG, 36 | kafkaConfigData.getSchemaRegistryUrl()); 37 | streamsConfiguration.put(StreamsConfig.DEFAULT_KEY_SERDE_CLASS_CONFIG, Serdes.String().getClass().getName()); 38 | streamsConfiguration.put(StreamsConfig.DEFAULT_VALUE_SERDE_CLASS_CONFIG, Serdes.String().getClass().getName()); 39 | streamsConfiguration.put(StreamsConfig.STATE_DIR_CONFIG, kafkaStreamsConfigData.getStateFileLocation()); 40 | return streamsConfiguration; 41 | } 42 | 43 | 44 | } 45 | -------------------------------------------------------------------------------- /microservices/microservices-demo/kafka-streams-service/src/main/java/com/microservices/demo/kafka/streams/service/controller/KafkaStreamsController.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.kafka.streams.service.controller; 2 | 3 | import com.microservices.demo.kafka.streams.service.model.KafkaStreamsResponseModel; 4 | import com.microservices.demo.kafka.streams.service.runner.StreamsRunner; 5 | import lombok.RequiredArgsConstructor; 6 | import lombok.extern.slf4j.Slf4j; 7 | import org.springframework.http.ResponseEntity; 8 | import org.springframework.security.access.prepost.PreAuthorize; 9 | import org.springframework.web.bind.annotation.*; 10 | 11 | import javax.validation.constraints.NotEmpty; 12 | 13 | @Slf4j 14 | @RestController 15 | @RequiredArgsConstructor 16 | @PreAuthorize("isAuthenticated()") 17 | @RequestMapping(value = "/", produces = "application/json") 18 | public class KafkaStreamsController { 19 | 20 | private final StreamsRunner streamsRunner; 21 | 22 | @GetMapping("/share-streams/{shareName}") 23 | @ResponseBody 24 | public ResponseEntity getShareStreams(@PathVariable @NotEmpty String shareName) { 25 | var response = streamsRunner.getValueByKey (shareName); 26 | log.info("Response: {}", response); 27 | return ResponseEntity.ok(KafkaStreamsResponseModel.builder() 28 | .shareName(shareName) 29 | .shareVolume(response) 30 | .build()); 31 | } 32 | 33 | 34 | } 35 | -------------------------------------------------------------------------------- /microservices/microservices-demo/kafka-streams-service/src/main/java/com/microservices/demo/kafka/streams/service/init/StreamsInitializer.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.kafka.streams.service.init; 2 | 3 | public interface StreamsInitializer { 4 | void init(); 5 | } 6 | -------------------------------------------------------------------------------- /microservices/microservices-demo/kafka-streams-service/src/main/java/com/microservices/demo/kafka/streams/service/init/impl/KafkaStreamsInitializer.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.kafka.streams.service.init.impl; 2 | 3 | import com.microservices.demo.config.KafkaConfigData; 4 | import com.microservices.demo.kafka.admin.client.KafkaAdminClient; 5 | import com.microservices.demo.kafka.streams.service.init.StreamsInitializer; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | import org.springframework.stereotype.Component; 9 | 10 | @Component 11 | public class KafkaStreamsInitializer implements StreamsInitializer { 12 | 13 | private static final Logger LOG = LoggerFactory.getLogger(KafkaStreamsInitializer.class); 14 | 15 | private final KafkaConfigData kafkaConfigData; 16 | 17 | private final KafkaAdminClient kafkaAdminClient; 18 | 19 | public KafkaStreamsInitializer(KafkaConfigData configData, KafkaAdminClient adminClient) { 20 | this.kafkaConfigData = configData; 21 | this.kafkaAdminClient = adminClient; 22 | } 23 | 24 | @Override 25 | public void init() { 26 | kafkaAdminClient.checkTopicsCreated(); 27 | kafkaAdminClient.checkSchemaRegistry(); 28 | LOG.info("Topics with name {} is ready for operations!", kafkaConfigData.getTopicNamesToCreate().toArray()); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /microservices/microservices-demo/kafka-streams-service/src/main/java/com/microservices/demo/kafka/streams/service/model/KafkaStreamsResponseModel.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.kafka.streams.service.model; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | @Data 9 | @Builder 10 | @NoArgsConstructor 11 | @AllArgsConstructor 12 | public class KafkaStreamsResponseModel { 13 | private String shareName; 14 | private String shareVolume; 15 | } 16 | -------------------------------------------------------------------------------- /microservices/microservices-demo/kafka-streams-service/src/main/java/com/microservices/demo/kafka/streams/service/runner/StreamsRunner.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.kafka.streams.service.runner; 2 | 3 | public interface StreamsRunner { 4 | void start(); 5 | String getValueByKey(K key); 6 | } 7 | -------------------------------------------------------------------------------- /microservices/microservices-demo/kafka-streams-service/src/main/java/com/microservices/demo/kafka/streams/service/security/AudienceValidator.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.kafka.streams.service.security; 2 | 3 | import com.microservices.demo.config.KafkaStreamsServiceConfigData; 4 | import org.springframework.beans.factory.annotation.Qualifier; 5 | import org.springframework.security.oauth2.core.OAuth2Error; 6 | import org.springframework.security.oauth2.core.OAuth2TokenValidator; 7 | import org.springframework.security.oauth2.core.OAuth2TokenValidatorResult; 8 | import org.springframework.security.oauth2.jwt.Jwt; 9 | import org.springframework.stereotype.Component; 10 | 11 | @Component 12 | @Qualifier(value = "kafka-streams-service-audience-validator") 13 | public class AudienceValidator implements OAuth2TokenValidator { 14 | 15 | private final KafkaStreamsServiceConfigData kafkaStreamsServiceConfig; 16 | 17 | public AudienceValidator(KafkaStreamsServiceConfigData config) { 18 | kafkaStreamsServiceConfig = config; 19 | } 20 | 21 | public OAuth2TokenValidatorResult validate(Jwt jwt) { 22 | if (jwt.getAudience().contains(kafkaStreamsServiceConfig.getCustomAudience())) { 23 | return OAuth2TokenValidatorResult.success(); 24 | } else { 25 | OAuth2Error audienceError = 26 | new OAuth2Error("invalid_token", "The required audience " + 27 | kafkaStreamsServiceConfig.getCustomAudience() + " is missing!", 28 | null); 29 | return OAuth2TokenValidatorResult.failure(audienceError); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /microservices/microservices-demo/kafka-streams-service/src/main/java/com/microservices/demo/kafka/streams/service/security/KafkaStreamsUser.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.kafka.streams.service.security; 2 | 3 | import lombok.Builder; 4 | import lombok.Getter; 5 | import org.springframework.security.core.GrantedAuthority; 6 | import org.springframework.security.core.userdetails.UserDetails; 7 | 8 | import java.util.Collection; 9 | 10 | import static com.microservices.demo.kafka.streams.service.Constants.NA; 11 | 12 | 13 | @Builder 14 | @Getter 15 | public class KafkaStreamsUser implements UserDetails { 16 | 17 | private String username; 18 | 19 | private Collection authorities; 20 | 21 | public void setAuthorities(Collection authorities) { 22 | this.authorities = authorities; 23 | } 24 | 25 | @Override 26 | public Collection getAuthorities() { 27 | return authorities; 28 | } 29 | 30 | @Override 31 | public String getPassword() { 32 | return NA; 33 | } 34 | 35 | @Override 36 | public String getUsername() { 37 | return username; 38 | } 39 | 40 | @Override 41 | public boolean isAccountNonExpired() { 42 | return true; 43 | } 44 | 45 | @Override 46 | public boolean isAccountNonLocked() { 47 | return true; 48 | } 49 | 50 | @Override 51 | public boolean isCredentialsNonExpired() { 52 | return true; 53 | } 54 | 55 | @Override 56 | public boolean isEnabled() { 57 | return true; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /microservices/microservices-demo/kafka-streams-service/src/main/java/com/microservices/demo/kafka/streams/service/security/KafkaStreamsUserDetailsService.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.kafka.streams.service.security; 2 | 3 | import org.springframework.security.core.userdetails.UserDetails; 4 | import org.springframework.security.core.userdetails.UserDetailsService; 5 | import org.springframework.security.core.userdetails.UsernameNotFoundException; 6 | import org.springframework.stereotype.Service; 7 | 8 | @Service 9 | public class KafkaStreamsUserDetailsService implements UserDetailsService { 10 | 11 | @Override 12 | public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { 13 | return KafkaStreamsUser.builder() 14 | .username(username) 15 | .build(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /microservices/microservices-demo/kafka-streams-service/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: kafka-streams-service 4 | profiles: 5 | active: kafka_streams_service 6 | cloud: 7 | config: 8 | name: kafka-streams-service,config-client 9 | uri: http://config-server:8888 10 | enabled: true 11 | username: spring_cloud_user 12 | password: spring_cloud_password 13 | config: 14 | import: configserver:http://config-server:8888 15 | 16 | eureka: 17 | client: 18 | serviceUrl: 19 | defaultZone: http://localhost:8761/eureka/ 20 | instance: 21 | lease-expiration-duration-in-seconds: 5 22 | lease-renewal-interval-in-seconds: 2 -------------------------------------------------------------------------------- /microservices/microservices-demo/kafka-streams-service/src/main/resources/banner.txt: -------------------------------------------------------------------------------- 1 | _ _ _ ___ _ _ _ _ ___ 2 | /_\ | | (_) / __| /_\ | \| | | | |_ _| 3 | / _ \ | | | | | (__ / _ \ | .` | | |__ | | 4 | /_/ \_\ |_| |_| \___| /_/ \_\ |_|\_| |____| |___| 5 | 6 | ${application.title} ${application.version} 7 | Powered by Spring Boot ${spring-boot.version} -------------------------------------------------------------------------------- /microservices/microservices-demo/kafka-streams-service/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /microservices/microservices-demo/kafka-to-elastic-service/src/main/java/com/microservices/demo/kafka/to/elastic/service/KafkaToElasticServiceApp.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.kafka.to.elastic.service; 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.context.annotation.ComponentScan; 7 | 8 | @EnableDiscoveryClient 9 | @SpringBootApplication 10 | @ComponentScan(basePackages = "com.microservices.demo") 11 | public class KafkaToElasticServiceApp { 12 | 13 | public static void main(String[] args) { 14 | SpringApplication.run(KafkaToElasticServiceApp.class, args); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /microservices/microservices-demo/kafka-to-elastic-service/src/main/java/com/microservices/demo/kafka/to/elastic/service/consumer/KafkaConsumer.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.kafka.to.elastic.service.consumer; 2 | 3 | import org.apache.avro.specific.SpecificRecordBase; 4 | 5 | import java.io.Serializable; 6 | import java.util.List; 7 | 8 | public interface KafkaConsumer { 9 | void receive(List messages, List keys , List partitions , List offsets); 10 | } 11 | -------------------------------------------------------------------------------- /microservices/microservices-demo/kafka-to-elastic-service/src/main/java/com/microservices/demo/kafka/to/elastic/service/converter/AvroToElasticConverter.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.kafka.to.elastic.service.converter; 2 | 3 | import com.microservices.demo.elastic.model.index.impl.FinanceIndexModel; 4 | import com.microservices.demo.elastic.model.index.model.FinanceAvroDTO; 5 | import com.microservices.demo.kafka.avro.model.FinanceAvroModel; 6 | import org.springframework.stereotype.Component; 7 | 8 | import java.time.Instant; 9 | import java.time.ZoneId; 10 | import java.time.ZonedDateTime; 11 | import java.util.List; 12 | 13 | @Component 14 | public class AvroToElasticConverter { 15 | 16 | public List getElasticModels(List avroModels){ 17 | 18 | return avroModels.stream() 19 | .map(avroModel -> FinanceIndexModel 20 | .builder() 21 | .id(avroModel.getId()) 22 | .shareData(FinanceAvroDTO 23 | .builder() 24 | .c(avroModel.getShareData().getC()) 25 | .dailyChangePercentage(avroModel.getShareData().getDailyChangePercentage()) 26 | .dailyVolume(avroModel.getShareData().getDailyVolume()) 27 | .description(avroModel.getShareData().getDescription()) 28 | .dailyChange(avroModel.getShareData().getDailyChange()) 29 | .previousDayClose(avroModel.getShareData().getPreviousDayClose()) 30 | .last(avroModel.getShareData().getLast()) 31 | .build()) 32 | .createdAt(ZonedDateTime.ofInstant(Instant.ofEpochMilli(avroModel.getCreatedAt()), 33 | ZoneId.systemDefault())) 34 | .build() 35 | ).toList(); 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /microservices/microservices-demo/kafka-to-elastic-service/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: kafka-to-elastic-service 4 | profiles: 5 | active: kafka_to_elastic 6 | cloud: 7 | config: 8 | name: finance-stream-service,config-client 9 | uri: http://config-server:8888 10 | enabled: true 11 | username: spring_cloud_user 12 | password: spring_cloud_password 13 | config: 14 | import: configserver:http://config-server:8888 15 | 16 | eureka: 17 | client: 18 | serviceUrl: 19 | defaultZone: http://localhost:8761/eureka/ 20 | instance: 21 | lease-expiration-duration-in-seconds: 5 22 | lease-renewal-interval-in-seconds: 2 -------------------------------------------------------------------------------- /microservices/microservices-demo/kafka-to-elastic-service/src/main/resources/banner.txt: -------------------------------------------------------------------------------- 1 | _ _ _ ___ _ _ _ _ ___ 2 | /_\ | | (_) / __| /_\ | \| | | | |_ _| 3 | / _ \ | | | | | (__ / _ \ | .` | | |__ | | 4 | /_/ \_\ |_| |_| \___| /_/ \_\ |_|\_| |____| |___| 5 | 6 | ${application.title} ${application.version} 7 | Powered by Spring Boot ${spring-boot.version} -------------------------------------------------------------------------------- /microservices/microservices-demo/kafka-to-elastic-service/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /microservices/microservices-demo/kafka/kafka-admin/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | microservices-demo 7 | com.microservices.demo 8 | 0.0.1-SNAPSHOT 9 | ../../pom.xml 10 | 11 | 4.0.0 12 | 13 | kafka-admin 14 | 15 | 16 | 17 | com.microservices.demo 18 | app-config-data 19 | 20 | 21 | 22 | com.microservices.demo 23 | common-config 24 | 25 | 26 | 27 | org.springframework.kafka 28 | spring-kafka 29 | 30 | 31 | 32 | org.springframework.boot 33 | spring-boot-starter-webflux 34 | 35 | 36 | 37 | 38 | org.projectlombok 39 | lombok 40 | compile 41 | 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /microservices/microservices-demo/kafka/kafka-admin/src/main/java/com/microservices/demo/kafka/admin/config/KafkaAdminConfig.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.kafka.admin.config; 2 | 3 | import com.microservices.demo.config.KafkaConfigData; 4 | import lombok.RequiredArgsConstructor; 5 | import org.apache.kafka.clients.CommonClientConfigs; 6 | import org.apache.kafka.clients.admin.AdminClient; 7 | import org.springframework.context.annotation.Bean; 8 | import org.springframework.context.annotation.Configuration; 9 | import org.springframework.retry.annotation.EnableRetry; 10 | 11 | import java.util.Map; 12 | 13 | @Configuration 14 | @EnableRetry 15 | @RequiredArgsConstructor 16 | public class KafkaAdminConfig { 17 | 18 | private final KafkaConfigData kafkaConfigData; 19 | 20 | @Bean 21 | public AdminClient adminClient() { 22 | return AdminClient.create(Map.of(CommonClientConfigs.BOOTSTRAP_SERVERS_CONFIG, 23 | kafkaConfigData.getBootstrapServers())); 24 | } 25 | 26 | 27 | } 28 | -------------------------------------------------------------------------------- /microservices/microservices-demo/kafka/kafka-admin/src/main/java/com/microservices/demo/kafka/admin/config/WebClientConfig.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.kafka.admin.config; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.web.reactive.function.client.WebClient; 6 | 7 | @Configuration 8 | public class WebClientConfig { 9 | 10 | @Bean 11 | WebClient webClient() { 12 | return WebClient.builder().build(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /microservices/microservices-demo/kafka/kafka-admin/src/main/java/com/microservices/demo/kafka/admin/exception/KafkaClientException.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.kafka.admin.exception; 2 | 3 | public class KafkaClientException extends RuntimeException{ 4 | public KafkaClientException(String message) { 5 | super(message); 6 | } 7 | public KafkaClientException(){ 8 | 9 | } 10 | public KafkaClientException(String message, Throwable cause) { 11 | super(message, cause); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /microservices/microservices-demo/kafka/kafka-consumer/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | microservices-demo 7 | com.microservices.demo 8 | 0.0.1-SNAPSHOT 9 | ../../pom.xml 10 | 11 | 4.0.0 12 | 13 | kafka-consumer 14 | 15 | 16 | 17 | com.microservices.demo 18 | app-config-data 19 | 20 | 21 | 22 | org.springframework.kafka 23 | spring-kafka 24 | 25 | 26 | 27 | org.apache.avro 28 | avro 29 | 30 | 31 | org.projectlombok 32 | lombok 33 | compile 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /microservices/microservices-demo/kafka/kafka-consumer/src/main/java/com/microservices/demo/kafka/consumer/config/api/KafkaConsumer.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.kafka.consumer.config.api; 2 | 3 | 4 | import org.apache.avro.specific.SpecificRecordBase; 5 | 6 | import java.util.List; 7 | 8 | public interface KafkaConsumer { 9 | void receive(List messages, List keys, List partitions, List offsets); 10 | } 11 | -------------------------------------------------------------------------------- /microservices/microservices-demo/kafka/kafka-model/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | microservices-demo 7 | com.microservices.demo 8 | 0.0.1-SNAPSHOT 9 | ../../pom.xml 10 | 11 | 4.0.0 12 | 13 | kafka-model 14 | 15 | 16 | 17 | 18 | org.apache.avro 19 | avro 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | org.apache.avro 29 | avro-maven-plugin 30 | ${avro.version} 31 | 32 | String 33 | 34 | 35 | 36 | generate-sources 37 | 38 | schema 39 | 40 | 41 | ${project.basedir}/src/main/resources/avro/ 42 | ${project.basedir}/src/main/java/ 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /microservices/microservices-demo/kafka/kafka-model/src/main/resources/avro/finance-analytics.avsc: -------------------------------------------------------------------------------- 1 | {"namespace": "com.microservices.demo.kafka.avro.model", 2 | "type": "record", 3 | "name": "FinanceAnalyticsAvroModel", 4 | "fields": [ 5 | {"name": "share", "type": ["null", "string"]}, 6 | {"name": "shareVolume", "type": ["null", "string"]}, 7 | {"name": "createdAt", "type": ["null", "long"], "logicalType": ["null", "date"]} 8 | ] 9 | } -------------------------------------------------------------------------------- /microservices/microservices-demo/kafka/kafka-model/src/main/resources/avro/finance.avsc: -------------------------------------------------------------------------------- 1 | 2 | { 3 | "namespace": "com.microservices.demo.kafka.avro.model", 4 | "type": "record", 5 | "name": "FinanceAvroModel", 6 | "fields": [ 7 | { 8 | "name": "id", 9 | "type": { 10 | "type": "string", 11 | "logicalType": "uuid" 12 | } 13 | }, 14 | { 15 | "name": "shareData", 16 | "type": { 17 | "name": "Share", 18 | "type": "record", 19 | "fields": [ 20 | { 21 | "name": "dailyChangePercentage", 22 | "type": "string" 23 | }, 24 | { 25 | "name": "dailyChange", 26 | "type": "string" 27 | }, 28 | { 29 | "name": "c", 30 | "type": "string" 31 | }, 32 | { 33 | "name": "last", 34 | "type": "string" 35 | }, 36 | { 37 | "name": "dailyVolume", 38 | "type": "string" 39 | }, 40 | { 41 | "name": "previousDayClose", 42 | "type": "string" 43 | }, 44 | { 45 | "name": "description", 46 | "type": "string" 47 | } 48 | ] 49 | } 50 | }, 51 | { 52 | "name": "createdAt", 53 | "type": ["null", "long"], 54 | "logicalType": ["null", "date"] 55 | } 56 | ] 57 | } -------------------------------------------------------------------------------- /microservices/microservices-demo/kafka/kafka-producer/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | microservices-demo 7 | com.microservices.demo 8 | 0.0.1-SNAPSHOT 9 | ../../pom.xml 10 | 11 | 4.0.0 12 | 13 | kafka-producer 14 | 15 | 16 | 17 | 18 | com.microservices.demo 19 | app-config-data 20 | 21 | 22 | 23 | com.microservices.demo 24 | kafka-model 25 | 26 | 27 | 28 | org.springframework.kafka 29 | spring-kafka 30 | 31 | 32 | 33 | io.confluent 34 | kafka-avro-serializer 35 | 36 | 37 | org.projectlombok 38 | lombok 39 | compile 40 | 41 | 42 | jakarta.annotation 43 | jakarta.annotation-api 44 | 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /microservices/microservices-demo/kafka/kafka-producer/src/main/java/com/microservices/demo/kafka/producer/config/service/KafkaProducer.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.kafka.producer.config.service; 2 | 3 | import org.apache.avro.specific.SpecificRecordBase; 4 | 5 | import java.io.Serializable; 6 | 7 | public interface KafkaProducer { 8 | void send(String topic, K key, V message); 9 | } 10 | -------------------------------------------------------------------------------- /microservices/microservices-demo/kafka/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | microservices-demo 7 | com.microservices.demo 8 | 0.0.1-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | kafka 13 | 14 | -------------------------------------------------------------------------------- /microservices/microservices-demo/mdc-interceptor/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | microservices-demo 7 | com.microservices.demo 8 | 0.0.1-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | mdc-interceptor 13 | 14 | 15 | 16 | org.springframework 17 | spring-context 18 | compile 19 | 20 | 21 | org.springframework 22 | spring-webmvc 23 | compile 24 | 25 | 26 | javax.servlet 27 | javax.servlet-api 28 | compile 29 | 30 | 31 | org.slf4j 32 | slf4j-api 33 | compile 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /microservices/microservices-demo/mdc-interceptor/src/main/java/com/microservices/demo/mdc/Constants.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.mdc; 2 | 3 | public class Constants { 4 | public static final String CORRELATION_ID_HEADER = "X-Correlation-ID"; 5 | public static final String CORRELATION_ID_KEY = "correlationID"; 6 | } 7 | -------------------------------------------------------------------------------- /microservices/microservices-demo/mdc-interceptor/src/main/java/com/microservices/demo/mdc/config/IdGeneratorConfig.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.mdc.config; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.util.IdGenerator; 6 | import org.springframework.util.JdkIdGenerator; 7 | 8 | @Configuration 9 | public class IdGeneratorConfig { 10 | 11 | @Bean 12 | public IdGenerator idGenerator() { 13 | return new JdkIdGenerator(); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /microservices/microservices-demo/mdc-interceptor/src/main/java/com/microservices/demo/mdc/config/WebMvcConfig.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.mdc.config; 2 | 3 | import com.microservices.demo.mdc.interceptor.MDCHandlerInterceptor; 4 | import org.springframework.stereotype.Component; 5 | import org.springframework.web.servlet.config.annotation.InterceptorRegistry; 6 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; 7 | 8 | @Component 9 | public class WebMvcConfig implements WebMvcConfigurer { 10 | 11 | private final MDCHandlerInterceptor mdcHandlerInterceptor; 12 | 13 | public WebMvcConfig(MDCHandlerInterceptor handlerInterceptor) { 14 | this.mdcHandlerInterceptor = handlerInterceptor; 15 | } 16 | 17 | @Override 18 | public void addInterceptors(InterceptorRegistry registry) { 19 | registry.addInterceptor(mdcHandlerInterceptor); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /microservices/microservices-demo/mdc-interceptor/src/main/java/com/microservices/demo/mdc/interceptor/MDCHandlerInterceptor.java: -------------------------------------------------------------------------------- 1 | package com.microservices.demo.mdc.interceptor; 2 | 3 | import com.microservices.demo.mdc.Constants; 4 | import org.slf4j.MDC; 5 | import org.springframework.stereotype.Component; 6 | import org.springframework.util.IdGenerator; 7 | import org.springframework.util.StringUtils; 8 | import org.springframework.web.servlet.HandlerInterceptor; 9 | 10 | import javax.servlet.http.HttpServletRequest; 11 | import javax.servlet.http.HttpServletResponse; 12 | 13 | 14 | @Component 15 | public class MDCHandlerInterceptor implements HandlerInterceptor { 16 | 17 | private final IdGenerator idGenerator; 18 | 19 | public MDCHandlerInterceptor(IdGenerator idGenerator) { 20 | this.idGenerator = idGenerator; 21 | } 22 | 23 | @Override 24 | public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) 25 | throws Exception { 26 | String correlationId = request.getHeader(Constants.CORRELATION_ID_HEADER); 27 | if (!StringUtils.isEmpty(correlationId)) { 28 | MDC.put(Constants.CORRELATION_ID_KEY, correlationId); 29 | } else { 30 | MDC.put(Constants.CORRELATION_ID_KEY, getNewCorrelationId()); 31 | } 32 | return true; 33 | } 34 | 35 | @Override 36 | public void afterCompletion(HttpServletRequest request, 37 | HttpServletResponse response, 38 | Object handler, 39 | Exception ex) { 40 | MDC.remove(Constants.CORRELATION_ID_KEY); 41 | } 42 | 43 | private String getNewCorrelationId() { 44 | return idGenerator.generateId().toString(); 45 | } 46 | } 47 | --------------------------------------------------------------------------------