├── .DS_Store
├── .gitignore
├── Modern Uygulamalarda Kafka Kullanımı.pptx
├── README.md
├── images
├── add_bucket.png
├── add_bucket_to_cluster.png
├── add_user.png
├── admin_user_settings.png
├── couchbase_ui.png
├── create_index.png
├── created_tables.png
├── data_grip.png
├── db.png
├── docker_desktop.png
├── edit_run_configuration.png
├── kafka_ui.png
├── open_runner.png
├── postman_request.png
├── rebalance.png
├── rebalance_result.png
├── run_ep.png
├── select_spring_boot.png
├── spring_new_instance_settings.png
├── success.png
├── system_architecture.png
└── topic_settings.png
├── notification-consumer
├── .gitignore
├── .mvn
│ └── wrapper
│ │ ├── maven-wrapper.jar
│ │ └── maven-wrapper.properties
├── infra-setup
│ └── docker-compose.yml
├── mvnw
├── mvnw.cmd
├── pom.xml
└── src
│ ├── main
│ ├── java
│ │ └── com
│ │ │ └── example
│ │ │ └── notificationconsumer
│ │ │ ├── NotificationConsumerApplication.java
│ │ │ ├── config
│ │ │ └── couchbase
│ │ │ │ └── MyCouchbaseConfig.java
│ │ │ ├── consumers
│ │ │ ├── configuration
│ │ │ │ ├── UserCreatedKafkaConsumerConfiguration.java
│ │ │ │ └── properties
│ │ │ │ │ └── UserCreatedConsumerProperties.java
│ │ │ ├── consumer
│ │ │ │ └── UserCreatedEventConsumer.java
│ │ │ └── model
│ │ │ │ └── UserCreatedEvent.java
│ │ │ ├── entity
│ │ │ └── Notification.java
│ │ │ ├── repository
│ │ │ └── NotificationRepository.java
│ │ │ └── service
│ │ │ └── NotificationService.java
│ └── resources
│ │ └── application.yml
│ └── test
│ └── java
│ └── com
│ └── example
│ └── notificationconsumer
│ └── NotificationConsumerApplicationTests.java
├── postman
├── Kafka-Example.postman_collection.json
└── MOCK_DATA.json
├── user-address-service
├── .gitignore
├── .mvn
│ └── wrapper
│ │ ├── maven-wrapper.jar
│ │ └── maven-wrapper.properties
├── infra-setup
│ └── docker-compose.yml
├── mvnw
├── mvnw.cmd
├── pom.xml
└── src
│ ├── main
│ ├── java
│ │ └── com
│ │ │ └── example
│ │ │ └── useraddressservice
│ │ │ ├── UserAddressServiceApplication.java
│ │ │ ├── consumers
│ │ │ ├── configuration
│ │ │ │ ├── UserCreatedKafkaConsumerConfiguration.java
│ │ │ │ └── properties
│ │ │ │ │ └── UserCreatedConsumerProperties.java
│ │ │ ├── consumer
│ │ │ │ └── UserCreatedEventConsumer.java
│ │ │ └── model
│ │ │ │ └── UserCreatedEvent.java
│ │ │ ├── controller
│ │ │ └── AddressController.java
│ │ │ ├── entity
│ │ │ └── Address.java
│ │ │ ├── repository
│ │ │ └── AddressRepository.java
│ │ │ └── service
│ │ │ └── AddressService.java
│ └── resources
│ │ └── application.yml
│ └── test
│ └── java
│ └── com
│ └── example
│ └── useraddressservice
│ └── UserAddressServiceApplicationTests.java
└── user-service
├── .gitignore
├── .mvn
└── wrapper
│ ├── maven-wrapper.jar
│ └── maven-wrapper.properties
├── infra-setup
└── docker-compose.yml
├── mvnw
├── mvnw.cmd
├── pom.xml
└── src
├── main
├── java
│ └── com
│ │ └── example
│ │ └── userservice
│ │ ├── UserServiceApplication.java
│ │ ├── config
│ │ └── kafka
│ │ │ ├── configuration
│ │ │ └── KafkaProducerConfiguration.java
│ │ │ ├── producer
│ │ │ └── KafkaProducer.java
│ │ │ └── properties
│ │ │ └── UserCreatedTopicProperties.java
│ │ ├── controller
│ │ └── UserController.java
│ │ ├── dto
│ │ ├── AddressResponseDto.java
│ │ ├── BaseResponseDto.java
│ │ ├── UserCreateRequest.java
│ │ ├── UserCreatedPayload.java
│ │ └── UserResponse.java
│ │ ├── entity
│ │ ├── BaseEntity.java
│ │ └── User.java
│ │ ├── repository
│ │ └── UserRepository.java
│ │ └── service
│ │ └── UserService.java
└── resources
│ └── application.yml
└── test
└── java
└── com
└── example
└── userservice
└── UserServiceApplicationTests.java
/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/muhammedsedef/Kafka-Example/3f0c43cc29d45a14d6c01a410e627dc2b6330cfa/.DS_Store
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | HELP.md
2 | target/
3 | !.mvn/wrapper/maven-wrapper.jar
4 | !**/src/main/**/target/
5 | !**/src/test/**/target/
6 | .DS_Store
7 |
8 | ### STS ###
9 | .apt_generated
10 | .classpath
11 | .factorypath
12 | .project
13 | .settings
14 | .springBeans
15 | .sts4-cache
16 |
17 | ### IntelliJ IDEA ###
18 | .idea
19 | *.iws
20 | *.iml
21 | *.ipr
22 |
23 | ### NetBeans ###
24 | /nbproject/private/
25 | /nbbuild/
26 | /dist/
27 | /nbdist/
28 | /.nb-gradle/
29 | build/
30 | !**/src/main/**/build/
31 | !**/src/test/**/build/
32 |
33 | ### VS Code ###
34 | .vscode/
35 |
--------------------------------------------------------------------------------
/Modern Uygulamalarda Kafka Kullanımı.pptx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/muhammedsedef/Kafka-Example/3f0c43cc29d45a14d6c01a410e627dc2b6330cfa/Modern Uygulamalarda Kafka Kullanımı.pptx
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Kafka-Example
2 | In this project,
3 | - There are 3 microservices, when a user created via user-service that service insert a record onto user table(postgre)
4 | and it produce an event to **user_service.user_created.0** topic.
5 | - Notification-consumer service listen **user_service.user_created.0** topic and simulates the logic of sending
6 | notification after the event it consumes after notification is sending successfully service insert a record onto couchbase
7 | notification bucket.
8 | - User-address-service also listen user_service.user_created.0 topic and it consume events. According to user's address text
9 | information it insert a record onto user-address table(postgre)
10 |
11 | ## System Architechure
12 | 
13 |
14 | ## Requirements
15 | - [Java 11 JDK](https://www.oracle.com/tr/java/technologies/javase/jdk11-archive-downloads.html)
16 | - [Docker](https://www.docker.com/products/docker-desktop/)
17 | - [Data Grip](https://www.jetbrains.com/datagrip/download/#section=mac) or any other database GUIs
18 | - [Postman](https://www.postman.com/downloads/)
19 |
20 | ## Setup
21 | - Before run project you need to start docker desktop
22 | - After docker is up, run the docker-compose.yml (You can find it in the infra-setup folder.)
23 | - After the run docker-compose.yml file you will see docker desktop like this:
24 | 
25 | - Continue With DB Connection Part
26 |
27 | ## DB Connection
28 | # Postgre Connection:
29 | url: jdbc:postgresql://localhost:5432/kafka_example
30 | username: example
31 | password: example
32 |
33 | * After you successfully connect database, you will see like this in datagrip:
34 | 
35 |
36 | # Couchbase Connection & Settings
37 | - #### Open http://localhost:8091/ on your browser
38 |
39 | 
40 |
41 | username: Administrator
42 | password: 123456
43 |
44 | - #### Open the buckets tab and click the **ADD BUCKET**
45 | 
46 |
47 | - #### write the bucket name in our example => bucket name is **"notification"**
48 | 
49 |
50 | - #### After that open the query tab on the left side
51 | 
52 | - #### Run 2 query separately to create index on bucket
53 |
54 | 1) CREATE PRIMARY INDEX `idx_default_primary_notification` ON `notification`
55 | 2) CREATE INDEX `id` ON `notification`(`id`)
56 | - #### Open the Security tab on the left side and click the **ADD USER**
57 | 
58 | - #### After click the add user you will see a new popup and fill the informations like :
59 | Username: admin
60 | Full Name: admin
61 | Password: 123456
62 | Verify Password: 123456
63 | 
64 |
65 | # Running
66 | - #### Run each project application file on your code ide.
67 | - #### After you run 3 application successfully you can check postgre db on your GUI you have to see created 2 tables which names ara **user** and **user_address**
68 | 
69 | - #### Check Topic is created or not http://localhost:9090/ (kafka ui)
70 | 
71 | - #### If you have come this far without any problems, we can open postman and try a sample request.
72 | - #### You can import postman collection which I share in postman_collection folder
73 | 
74 | - #### After execute post endpoint and get 200 success message from postman you can see producer and consumer logs on your running terminal also you can check that records are in your databases
75 | 
76 | 
77 | - #### As you can see our records successfully inserted to our databases
78 | - #### To test batch request use MOCK DATA.json file which it is in postman folder, open the postman runner and select that json file and run.
79 | 
80 | 
81 |
82 | # Topic Partition Settings
83 | - #### To increase topic partition open http://localhost:9090/ (kafka-ui) and open the topic settings.
84 | 
85 | - #### As you can see I set partition count 4
86 | - #### After set partition count 4, now our consumer's will rebalance because now we have 4 partition so our consumers bind all of partitions
87 | 
88 | - #### If you want to run one more consumer app follow these steps:
89 | 
90 | 
91 | 
92 | - #### Now you can run one more consumer app, it will up randomly port in your computer's free port because we set server.port as 0 in application.yml
93 | 
94 | - #### As you can see we have 4 partition and we run 4 consumer app (user-address-service) so each consumer app bind 1 partition of user_service.user_created.0 topic
95 | - #### You can run again batch request on postman and you can easily see your consumer apps consume the event corresponding partition
96 |
97 |
98 |
99 |
100 |
--------------------------------------------------------------------------------
/images/add_bucket.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/muhammedsedef/Kafka-Example/3f0c43cc29d45a14d6c01a410e627dc2b6330cfa/images/add_bucket.png
--------------------------------------------------------------------------------
/images/add_bucket_to_cluster.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/muhammedsedef/Kafka-Example/3f0c43cc29d45a14d6c01a410e627dc2b6330cfa/images/add_bucket_to_cluster.png
--------------------------------------------------------------------------------
/images/add_user.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/muhammedsedef/Kafka-Example/3f0c43cc29d45a14d6c01a410e627dc2b6330cfa/images/add_user.png
--------------------------------------------------------------------------------
/images/admin_user_settings.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/muhammedsedef/Kafka-Example/3f0c43cc29d45a14d6c01a410e627dc2b6330cfa/images/admin_user_settings.png
--------------------------------------------------------------------------------
/images/couchbase_ui.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/muhammedsedef/Kafka-Example/3f0c43cc29d45a14d6c01a410e627dc2b6330cfa/images/couchbase_ui.png
--------------------------------------------------------------------------------
/images/create_index.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/muhammedsedef/Kafka-Example/3f0c43cc29d45a14d6c01a410e627dc2b6330cfa/images/create_index.png
--------------------------------------------------------------------------------
/images/created_tables.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/muhammedsedef/Kafka-Example/3f0c43cc29d45a14d6c01a410e627dc2b6330cfa/images/created_tables.png
--------------------------------------------------------------------------------
/images/data_grip.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/muhammedsedef/Kafka-Example/3f0c43cc29d45a14d6c01a410e627dc2b6330cfa/images/data_grip.png
--------------------------------------------------------------------------------
/images/db.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/muhammedsedef/Kafka-Example/3f0c43cc29d45a14d6c01a410e627dc2b6330cfa/images/db.png
--------------------------------------------------------------------------------
/images/docker_desktop.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/muhammedsedef/Kafka-Example/3f0c43cc29d45a14d6c01a410e627dc2b6330cfa/images/docker_desktop.png
--------------------------------------------------------------------------------
/images/edit_run_configuration.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/muhammedsedef/Kafka-Example/3f0c43cc29d45a14d6c01a410e627dc2b6330cfa/images/edit_run_configuration.png
--------------------------------------------------------------------------------
/images/kafka_ui.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/muhammedsedef/Kafka-Example/3f0c43cc29d45a14d6c01a410e627dc2b6330cfa/images/kafka_ui.png
--------------------------------------------------------------------------------
/images/open_runner.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/muhammedsedef/Kafka-Example/3f0c43cc29d45a14d6c01a410e627dc2b6330cfa/images/open_runner.png
--------------------------------------------------------------------------------
/images/postman_request.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/muhammedsedef/Kafka-Example/3f0c43cc29d45a14d6c01a410e627dc2b6330cfa/images/postman_request.png
--------------------------------------------------------------------------------
/images/rebalance.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/muhammedsedef/Kafka-Example/3f0c43cc29d45a14d6c01a410e627dc2b6330cfa/images/rebalance.png
--------------------------------------------------------------------------------
/images/rebalance_result.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/muhammedsedef/Kafka-Example/3f0c43cc29d45a14d6c01a410e627dc2b6330cfa/images/rebalance_result.png
--------------------------------------------------------------------------------
/images/run_ep.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/muhammedsedef/Kafka-Example/3f0c43cc29d45a14d6c01a410e627dc2b6330cfa/images/run_ep.png
--------------------------------------------------------------------------------
/images/select_spring_boot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/muhammedsedef/Kafka-Example/3f0c43cc29d45a14d6c01a410e627dc2b6330cfa/images/select_spring_boot.png
--------------------------------------------------------------------------------
/images/spring_new_instance_settings.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/muhammedsedef/Kafka-Example/3f0c43cc29d45a14d6c01a410e627dc2b6330cfa/images/spring_new_instance_settings.png
--------------------------------------------------------------------------------
/images/success.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/muhammedsedef/Kafka-Example/3f0c43cc29d45a14d6c01a410e627dc2b6330cfa/images/success.png
--------------------------------------------------------------------------------
/images/system_architecture.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/muhammedsedef/Kafka-Example/3f0c43cc29d45a14d6c01a410e627dc2b6330cfa/images/system_architecture.png
--------------------------------------------------------------------------------
/images/topic_settings.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/muhammedsedef/Kafka-Example/3f0c43cc29d45a14d6c01a410e627dc2b6330cfa/images/topic_settings.png
--------------------------------------------------------------------------------
/notification-consumer/.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 |
--------------------------------------------------------------------------------
/notification-consumer/.mvn/wrapper/maven-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/muhammedsedef/Kafka-Example/3f0c43cc29d45a14d6c01a410e627dc2b6330cfa/notification-consumer/.mvn/wrapper/maven-wrapper.jar
--------------------------------------------------------------------------------
/notification-consumer/.mvn/wrapper/maven-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.6/apache-maven-3.8.6-bin.zip
2 | wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar
3 |
--------------------------------------------------------------------------------
/notification-consumer/infra-setup/docker-compose.yml:
--------------------------------------------------------------------------------
1 | # Use postgres/example user/password credentials
2 | version: '3.1'
3 |
4 | services:
5 | couchbase-db:
6 | image: couchbase/server:community-aarch64
7 | ports:
8 | - 8091:8091
9 | - 8092:8092
10 | - 8093:8093
11 | - 11210:11210
12 | zookeeper:
13 | image: "docker.io/bitnami/zookeeper:3"
14 | ports:
15 | - "2181:2181"
16 | volumes:
17 | - "zookeeper_data:/bitnami"
18 | environment:
19 | - ALLOW_ANONYMOUS_LOGIN=yes
20 | kafka:
21 | image: "docker.io/bitnami/kafka:2-debian-10"
22 | ports:
23 | - "9092:9092"
24 | expose:
25 | - "9093"
26 | volumes:
27 | - "kafka_data:/bitnami"
28 | environment:
29 | - KAFKA_CFG_ZOOKEEPER_CONNECT=zookeeper:2181
30 | - ALLOW_PLAINTEXT_LISTENER=yes
31 | - KAFKA_ADVERTISED_LISTENERS=INSIDE://kafka:9093,OUTSIDE://localhost:9092
32 | - KAFKA_LISTENER_SECURITY_PROTOCOL_MAP=INSIDE:PLAINTEXT,OUTSIDE:PLAINTEXT
33 | - KAFKA_LISTENERS=INSIDE://0.0.0.0:9093,OUTSIDE://0.0.0.0:9092
34 | - KAFKA_INTER_BROKER_LISTENER_NAME=INSIDE
35 | - KAFKA_ZOOKEEPER_CONNECT=zookeeper:2181
36 | depends_on:
37 | - zookeeper
38 | kafka-ui:
39 | image: provectuslabs/kafka-ui
40 | container_name: kafka-ui
41 | ports:
42 | - "9090:8080"
43 | restart: always
44 | environment:
45 | - KAFKA_CLUSTERS_0_NAME=local
46 | - KAFKA_CLUSTERS_0_BOOTSTRAPSERVERS=kafka:9093
47 | - KAFKA_CLUSTERS_0_ZOOKEEPER=localhost:2181
48 |
49 | volumes:
50 | zookeeper_data:
51 | driver: local
52 | kafka_data:
53 | driver: local
--------------------------------------------------------------------------------
/notification-consumer/mvnw:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | # ----------------------------------------------------------------------------
3 | # Licensed to the Apache Software Foundation (ASF) under one
4 | # or more contributor license agreements. See the NOTICE file
5 | # distributed with this work for additional information
6 | # regarding copyright ownership. The ASF licenses this file
7 | # to you under the Apache License, Version 2.0 (the
8 | # "License"); you may not use this file except in compliance
9 | # with the License. You may obtain a copy of the License at
10 | #
11 | # https://www.apache.org/licenses/LICENSE-2.0
12 | #
13 | # Unless required by applicable law or agreed to in writing,
14 | # software distributed under the License is distributed on an
15 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 | # KIND, either express or implied. See the License for the
17 | # specific language governing permissions and limitations
18 | # under the License.
19 | # ----------------------------------------------------------------------------
20 |
21 | # ----------------------------------------------------------------------------
22 | # Maven Start Up Batch script
23 | #
24 | # Required ENV vars:
25 | # ------------------
26 | # JAVA_HOME - location of a JDK home dir
27 | #
28 | # Optional ENV vars
29 | # -----------------
30 | # M2_HOME - location of maven2's installed home dir
31 | # MAVEN_OPTS - parameters passed to the Java VM when running Maven
32 | # e.g. to debug Maven itself, use
33 | # set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
34 | # MAVEN_SKIP_RC - flag to disable loading of mavenrc files
35 | # ----------------------------------------------------------------------------
36 |
37 | if [ -z "$MAVEN_SKIP_RC" ] ; then
38 |
39 | if [ -f /usr/local/etc/mavenrc ] ; then
40 | . /usr/local/etc/mavenrc
41 | fi
42 |
43 | if [ -f /etc/mavenrc ] ; then
44 | . /etc/mavenrc
45 | fi
46 |
47 | if [ -f "$HOME/.mavenrc" ] ; then
48 | . "$HOME/.mavenrc"
49 | fi
50 |
51 | fi
52 |
53 | # OS specific support. $var _must_ be set to either true or false.
54 | cygwin=false;
55 | darwin=false;
56 | mingw=false
57 | case "`uname`" in
58 | CYGWIN*) cygwin=true ;;
59 | MINGW*) mingw=true;;
60 | Darwin*) darwin=true
61 | # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
62 | # See https://developer.apple.com/library/mac/qa/qa1170/_index.html
63 | if [ -z "$JAVA_HOME" ]; then
64 | if [ -x "/usr/libexec/java_home" ]; then
65 | export JAVA_HOME="`/usr/libexec/java_home`"
66 | else
67 | export JAVA_HOME="/Library/Java/Home"
68 | fi
69 | fi
70 | ;;
71 | esac
72 |
73 | if [ -z "$JAVA_HOME" ] ; then
74 | if [ -r /etc/gentoo-release ] ; then
75 | JAVA_HOME=`java-config --jre-home`
76 | fi
77 | fi
78 |
79 | if [ -z "$M2_HOME" ] ; then
80 | ## resolve links - $0 may be a link to maven's home
81 | PRG="$0"
82 |
83 | # need this for relative symlinks
84 | while [ -h "$PRG" ] ; do
85 | ls=`ls -ld "$PRG"`
86 | link=`expr "$ls" : '.*-> \(.*\)$'`
87 | if expr "$link" : '/.*' > /dev/null; then
88 | PRG="$link"
89 | else
90 | PRG="`dirname "$PRG"`/$link"
91 | fi
92 | done
93 |
94 | saveddir=`pwd`
95 |
96 | M2_HOME=`dirname "$PRG"`/..
97 |
98 | # make it fully qualified
99 | M2_HOME=`cd "$M2_HOME" && pwd`
100 |
101 | cd "$saveddir"
102 | # echo Using m2 at $M2_HOME
103 | fi
104 |
105 | # For Cygwin, ensure paths are in UNIX format before anything is touched
106 | if $cygwin ; then
107 | [ -n "$M2_HOME" ] &&
108 | M2_HOME=`cygpath --unix "$M2_HOME"`
109 | [ -n "$JAVA_HOME" ] &&
110 | JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
111 | [ -n "$CLASSPATH" ] &&
112 | CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
113 | fi
114 |
115 | # For Mingw, ensure paths are in UNIX format before anything is touched
116 | if $mingw ; then
117 | [ -n "$M2_HOME" ] &&
118 | M2_HOME="`(cd "$M2_HOME"; pwd)`"
119 | [ -n "$JAVA_HOME" ] &&
120 | JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
121 | fi
122 |
123 | if [ -z "$JAVA_HOME" ]; then
124 | javaExecutable="`which javac`"
125 | if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
126 | # readlink(1) is not available as standard on Solaris 10.
127 | readLink=`which readlink`
128 | if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
129 | if $darwin ; then
130 | javaHome="`dirname \"$javaExecutable\"`"
131 | javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
132 | else
133 | javaExecutable="`readlink -f \"$javaExecutable\"`"
134 | fi
135 | javaHome="`dirname \"$javaExecutable\"`"
136 | javaHome=`expr "$javaHome" : '\(.*\)/bin'`
137 | JAVA_HOME="$javaHome"
138 | export JAVA_HOME
139 | fi
140 | fi
141 | fi
142 |
143 | if [ -z "$JAVACMD" ] ; then
144 | if [ -n "$JAVA_HOME" ] ; then
145 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
146 | # IBM's JDK on AIX uses strange locations for the executables
147 | JAVACMD="$JAVA_HOME/jre/sh/java"
148 | else
149 | JAVACMD="$JAVA_HOME/bin/java"
150 | fi
151 | else
152 | JAVACMD="`\\unset -f command; \\command -v java`"
153 | fi
154 | fi
155 |
156 | if [ ! -x "$JAVACMD" ] ; then
157 | echo "Error: JAVA_HOME is not defined correctly." >&2
158 | echo " We cannot execute $JAVACMD" >&2
159 | exit 1
160 | fi
161 |
162 | if [ -z "$JAVA_HOME" ] ; then
163 | echo "Warning: JAVA_HOME environment variable is not set."
164 | fi
165 |
166 | CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
167 |
168 | # traverses directory structure from process work directory to filesystem root
169 | # first directory with .mvn subdirectory is considered project base directory
170 | find_maven_basedir() {
171 |
172 | if [ -z "$1" ]
173 | then
174 | echo "Path not specified to find_maven_basedir"
175 | return 1
176 | fi
177 |
178 | basedir="$1"
179 | wdir="$1"
180 | while [ "$wdir" != '/' ] ; do
181 | if [ -d "$wdir"/.mvn ] ; then
182 | basedir=$wdir
183 | break
184 | fi
185 | # workaround for JBEAP-8937 (on Solaris 10/Sparc)
186 | if [ -d "${wdir}" ]; then
187 | wdir=`cd "$wdir/.."; pwd`
188 | fi
189 | # end of workaround
190 | done
191 | echo "${basedir}"
192 | }
193 |
194 | # concatenates all lines of a file
195 | concat_lines() {
196 | if [ -f "$1" ]; then
197 | echo "$(tr -s '\n' ' ' < "$1")"
198 | fi
199 | }
200 |
201 | BASE_DIR=`find_maven_basedir "$(pwd)"`
202 | if [ -z "$BASE_DIR" ]; then
203 | exit 1;
204 | fi
205 |
206 | ##########################################################################################
207 | # Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
208 | # This allows using the maven wrapper in projects that prohibit checking in binary data.
209 | ##########################################################################################
210 | if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
211 | if [ "$MVNW_VERBOSE" = true ]; then
212 | echo "Found .mvn/wrapper/maven-wrapper.jar"
213 | fi
214 | else
215 | if [ "$MVNW_VERBOSE" = true ]; then
216 | echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
217 | fi
218 | if [ -n "$MVNW_REPOURL" ]; then
219 | jarUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
220 | else
221 | jarUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
222 | fi
223 | while IFS="=" read key value; do
224 | case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
225 | esac
226 | done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
227 | if [ "$MVNW_VERBOSE" = true ]; then
228 | echo "Downloading from: $jarUrl"
229 | fi
230 | wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
231 | if $cygwin; then
232 | wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"`
233 | fi
234 |
235 | if command -v wget > /dev/null; then
236 | if [ "$MVNW_VERBOSE" = true ]; then
237 | echo "Found wget ... using wget"
238 | fi
239 | if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
240 | wget "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
241 | else
242 | wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
243 | fi
244 | elif command -v curl > /dev/null; then
245 | if [ "$MVNW_VERBOSE" = true ]; then
246 | echo "Found curl ... using curl"
247 | fi
248 | if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
249 | curl -o "$wrapperJarPath" "$jarUrl" -f
250 | else
251 | curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f
252 | fi
253 |
254 | else
255 | if [ "$MVNW_VERBOSE" = true ]; then
256 | echo "Falling back to using Java to download"
257 | fi
258 | javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
259 | # For Cygwin, switch paths to Windows format before running javac
260 | if $cygwin; then
261 | javaClass=`cygpath --path --windows "$javaClass"`
262 | fi
263 | if [ -e "$javaClass" ]; then
264 | if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
265 | if [ "$MVNW_VERBOSE" = true ]; then
266 | echo " - Compiling MavenWrapperDownloader.java ..."
267 | fi
268 | # Compiling the Java class
269 | ("$JAVA_HOME/bin/javac" "$javaClass")
270 | fi
271 | if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
272 | # Running the downloader
273 | if [ "$MVNW_VERBOSE" = true ]; then
274 | echo " - Running MavenWrapperDownloader.java ..."
275 | fi
276 | ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
277 | fi
278 | fi
279 | fi
280 | fi
281 | ##########################################################################################
282 | # End of extension
283 | ##########################################################################################
284 |
285 | export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
286 | if [ "$MVNW_VERBOSE" = true ]; then
287 | echo $MAVEN_PROJECTBASEDIR
288 | fi
289 | MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
290 |
291 | # For Cygwin, switch paths to Windows format before running java
292 | if $cygwin; then
293 | [ -n "$M2_HOME" ] &&
294 | M2_HOME=`cygpath --path --windows "$M2_HOME"`
295 | [ -n "$JAVA_HOME" ] &&
296 | JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
297 | [ -n "$CLASSPATH" ] &&
298 | CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
299 | [ -n "$MAVEN_PROJECTBASEDIR" ] &&
300 | MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
301 | fi
302 |
303 | # Provide a "standardized" way to retrieve the CLI args that will
304 | # work with both Windows and non-Windows executions.
305 | MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
306 | export MAVEN_CMD_LINE_ARGS
307 |
308 | WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
309 |
310 | exec "$JAVACMD" \
311 | $MAVEN_OPTS \
312 | $MAVEN_DEBUG_OPTS \
313 | -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
314 | "-Dmaven.home=${M2_HOME}" \
315 | "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
316 | ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
317 |
--------------------------------------------------------------------------------
/notification-consumer/mvnw.cmd:
--------------------------------------------------------------------------------
1 | @REM ----------------------------------------------------------------------------
2 | @REM Licensed to the Apache Software Foundation (ASF) under one
3 | @REM or more contributor license agreements. See the NOTICE file
4 | @REM distributed with this work for additional information
5 | @REM regarding copyright ownership. The ASF licenses this file
6 | @REM to you under the Apache License, Version 2.0 (the
7 | @REM "License"); you may not use this file except in compliance
8 | @REM with the License. You may obtain a copy of the License at
9 | @REM
10 | @REM https://www.apache.org/licenses/LICENSE-2.0
11 | @REM
12 | @REM Unless required by applicable law or agreed to in writing,
13 | @REM software distributed under the License is distributed on an
14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | @REM KIND, either express or implied. See the License for the
16 | @REM specific language governing permissions and limitations
17 | @REM under the License.
18 | @REM ----------------------------------------------------------------------------
19 |
20 | @REM ----------------------------------------------------------------------------
21 | @REM Maven Start Up Batch script
22 | @REM
23 | @REM Required ENV vars:
24 | @REM JAVA_HOME - location of a JDK home dir
25 | @REM
26 | @REM Optional ENV vars
27 | @REM M2_HOME - location of maven2's installed home dir
28 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
29 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
30 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
31 | @REM e.g. to debug Maven itself, use
32 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
33 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
34 | @REM ----------------------------------------------------------------------------
35 |
36 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
37 | @echo off
38 | @REM set title of command window
39 | title %0
40 | @REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
41 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
42 |
43 | @REM set %HOME% to equivalent of $HOME
44 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
45 |
46 | @REM Execute a user defined script before this one
47 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
48 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending
49 | if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %*
50 | if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %*
51 | :skipRcPre
52 |
53 | @setlocal
54 |
55 | set ERROR_CODE=0
56 |
57 | @REM To isolate internal variables from possible post scripts, we use another setlocal
58 | @setlocal
59 |
60 | @REM ==== START VALIDATION ====
61 | if not "%JAVA_HOME%" == "" goto OkJHome
62 |
63 | echo.
64 | echo Error: JAVA_HOME not found in your environment. >&2
65 | echo Please set the JAVA_HOME variable in your environment to match the >&2
66 | echo location of your Java installation. >&2
67 | echo.
68 | goto error
69 |
70 | :OkJHome
71 | if exist "%JAVA_HOME%\bin\java.exe" goto init
72 |
73 | echo.
74 | echo Error: JAVA_HOME is set to an invalid directory. >&2
75 | echo JAVA_HOME = "%JAVA_HOME%" >&2
76 | echo Please set the JAVA_HOME variable in your environment to match the >&2
77 | echo location of your Java installation. >&2
78 | echo.
79 | goto error
80 |
81 | @REM ==== END VALIDATION ====
82 |
83 | :init
84 |
85 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
86 | @REM Fallback to current working directory if not found.
87 |
88 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
89 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
90 |
91 | set EXEC_DIR=%CD%
92 | set WDIR=%EXEC_DIR%
93 | :findBaseDir
94 | IF EXIST "%WDIR%"\.mvn goto baseDirFound
95 | cd ..
96 | IF "%WDIR%"=="%CD%" goto baseDirNotFound
97 | set WDIR=%CD%
98 | goto findBaseDir
99 |
100 | :baseDirFound
101 | set MAVEN_PROJECTBASEDIR=%WDIR%
102 | cd "%EXEC_DIR%"
103 | goto endDetectBaseDir
104 |
105 | :baseDirNotFound
106 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
107 | cd "%EXEC_DIR%"
108 |
109 | :endDetectBaseDir
110 |
111 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
112 |
113 | @setlocal EnableExtensions EnableDelayedExpansion
114 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
115 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
116 |
117 | :endReadAdditionalConfig
118 |
119 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
120 | set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
121 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
122 |
123 | set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
124 |
125 | FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
126 | IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
127 | )
128 |
129 | @REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
130 | @REM This allows using the maven wrapper in projects that prohibit checking in binary data.
131 | if exist %WRAPPER_JAR% (
132 | if "%MVNW_VERBOSE%" == "true" (
133 | echo Found %WRAPPER_JAR%
134 | )
135 | ) else (
136 | if not "%MVNW_REPOURL%" == "" (
137 | SET DOWNLOAD_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
138 | )
139 | if "%MVNW_VERBOSE%" == "true" (
140 | echo Couldn't find %WRAPPER_JAR%, downloading it ...
141 | echo Downloading from: %DOWNLOAD_URL%
142 | )
143 |
144 | powershell -Command "&{"^
145 | "$webclient = new-object System.Net.WebClient;"^
146 | "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
147 | "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
148 | "}"^
149 | "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^
150 | "}"
151 | if "%MVNW_VERBOSE%" == "true" (
152 | echo Finished downloading %WRAPPER_JAR%
153 | )
154 | )
155 | @REM End of extension
156 |
157 | @REM Provide a "standardized" way to retrieve the CLI args that will
158 | @REM work with both Windows and non-Windows executions.
159 | set MAVEN_CMD_LINE_ARGS=%*
160 |
161 | %MAVEN_JAVA_EXE% ^
162 | %JVM_CONFIG_MAVEN_PROPS% ^
163 | %MAVEN_OPTS% ^
164 | %MAVEN_DEBUG_OPTS% ^
165 | -classpath %WRAPPER_JAR% ^
166 | "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^
167 | %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
168 | if ERRORLEVEL 1 goto error
169 | goto end
170 |
171 | :error
172 | set ERROR_CODE=1
173 |
174 | :end
175 | @endlocal & set ERROR_CODE=%ERROR_CODE%
176 |
177 | if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost
178 | @REM check for post script, once with legacy .bat ending and once with .cmd ending
179 | if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat"
180 | if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd"
181 | :skipRcPost
182 |
183 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
184 | if "%MAVEN_BATCH_PAUSE%"=="on" pause
185 |
186 | if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE%
187 |
188 | cmd /C exit /B %ERROR_CODE%
189 |
--------------------------------------------------------------------------------
/notification-consumer/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | org.springframework.boot
7 | spring-boot-starter-parent
8 | 2.7.5
9 |
10 |
11 | com.example
12 | notification-consumer
13 | 0.0.1-SNAPSHOT
14 | notification-consumer
15 | notification-consumer
16 |
17 | 11
18 |
19 |
20 |
21 | org.springframework.boot
22 | spring-boot-starter-data-couchbase
23 |
24 |
25 | org.springframework.boot
26 | spring-boot-starter-web
27 |
28 |
29 | org.springframework.kafka
30 | spring-kafka
31 |
32 |
33 |
34 | org.springframework.boot
35 | spring-boot-configuration-processor
36 | true
37 |
38 |
39 |
40 | org.springframework.data
41 | spring-data-couchbase
42 |
43 |
44 |
45 | org.projectlombok
46 | lombok
47 | true
48 |
49 |
50 | org.springframework.boot
51 | spring-boot-starter-test
52 | test
53 |
54 |
55 | org.springframework.kafka
56 | spring-kafka-test
57 | test
58 |
59 |
60 |
61 |
62 |
63 |
64 | org.springframework.boot
65 | spring-boot-maven-plugin
66 |
67 |
68 |
69 | org.projectlombok
70 | lombok
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
--------------------------------------------------------------------------------
/notification-consumer/src/main/java/com/example/notificationconsumer/NotificationConsumerApplication.java:
--------------------------------------------------------------------------------
1 | package com.example.notificationconsumer;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 |
6 | @SpringBootApplication
7 | public class NotificationConsumerApplication {
8 |
9 | public static void main(String[] args) {
10 | SpringApplication.run(NotificationConsumerApplication.class, args);
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/notification-consumer/src/main/java/com/example/notificationconsumer/config/couchbase/MyCouchbaseConfig.java:
--------------------------------------------------------------------------------
1 | package com.example.notificationconsumer.config.couchbase;
2 |
3 | import org.springframework.beans.factory.annotation.Value;
4 | import org.springframework.context.annotation.Configuration;
5 | import org.springframework.data.couchbase.config.AbstractCouchbaseConfiguration;
6 |
7 | @Configuration
8 | public class MyCouchbaseConfig extends AbstractCouchbaseConfiguration {
9 |
10 |
11 | @Value("${couchbase.notification-service.config.bootstrapHosts}")
12 | private String connectionString;
13 |
14 | @Value("${couchbase.notification-service.config.notificationBucketUsername}")
15 | private String username;
16 |
17 | @Value("${couchbase.notification-service.config.notificationPassword}")
18 | private String password;
19 |
20 | @Value("${couchbase.notification-service.config.notificationBucket}")
21 | private String bucketName;
22 |
23 | @Override
24 | public String getConnectionString() {
25 | return connectionString;
26 | }
27 |
28 | @Override
29 | public String getUserName() {
30 | return username;
31 | }
32 |
33 | @Override
34 | public String getPassword() {
35 | return password;
36 | }
37 |
38 | @Override
39 | public String getBucketName() {
40 | return bucketName;
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/notification-consumer/src/main/java/com/example/notificationconsumer/consumers/configuration/UserCreatedKafkaConsumerConfiguration.java:
--------------------------------------------------------------------------------
1 | package com.example.notificationconsumer.consumers.configuration;
2 |
3 | import org.apache.kafka.common.serialization.StringDeserializer;
4 | import lombok.RequiredArgsConstructor;
5 | import org.apache.kafka.clients.consumer.ConsumerConfig;
6 | import org.springframework.beans.factory.annotation.Value;
7 | import org.springframework.context.annotation.Bean;
8 | import org.springframework.context.annotation.Configuration;
9 | import org.springframework.kafka.config.ConcurrentKafkaListenerContainerFactory;
10 | import org.springframework.kafka.core.ConsumerFactory;
11 | import org.springframework.kafka.core.DefaultKafkaConsumerFactory;
12 | import org.springframework.kafka.support.converter.StringJsonMessageConverter;
13 |
14 | import java.util.HashMap;
15 | import java.util.Map;
16 |
17 | @Configuration
18 | @RequiredArgsConstructor
19 | public class UserCreatedKafkaConsumerConfiguration {
20 |
21 | @Value("${kafka.host}")
22 | private String host;
23 |
24 | public ConsumerFactory consumerFactory() {
25 |
26 | // Creating a Map of string-object pairs
27 | Map config = new HashMap<>();
28 |
29 | // Adding the Configuration
30 | config.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, host);
31 | config.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);
32 | config.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);
33 | //config.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, true);
34 |
35 | return new DefaultKafkaConsumerFactory<>(config);
36 | }
37 |
38 | @Bean
39 | // Creating a Listener
40 | public ConcurrentKafkaListenerContainerFactory concurrentKafkaListenerContainerFactory() {
41 | ConcurrentKafkaListenerContainerFactory factory
42 | = new ConcurrentKafkaListenerContainerFactory<>();
43 | factory.setConsumerFactory(consumerFactory());
44 | factory.setMessageConverter(new StringJsonMessageConverter());
45 | return factory;
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/notification-consumer/src/main/java/com/example/notificationconsumer/consumers/configuration/properties/UserCreatedConsumerProperties.java:
--------------------------------------------------------------------------------
1 | package com.example.notificationconsumer.consumers.configuration.properties;
2 |
3 | import lombok.Getter;
4 | import lombok.Setter;
5 | import org.springframework.boot.context.properties.ConfigurationProperties;
6 | import org.springframework.context.annotation.Configuration;
7 |
8 | @Configuration
9 | @ConfigurationProperties(prefix = "kafka.topics.user-created")
10 | @Getter
11 | @Setter
12 | public class UserCreatedConsumerProperties {
13 | private String topic;
14 | private String consumerGroup;
15 | }
16 |
17 |
18 |
--------------------------------------------------------------------------------
/notification-consumer/src/main/java/com/example/notificationconsumer/consumers/consumer/UserCreatedEventConsumer.java:
--------------------------------------------------------------------------------
1 | package com.example.notificationconsumer.consumers.consumer;
2 |
3 | import com.example.notificationconsumer.consumers.model.UserCreatedEvent;
4 | import com.example.notificationconsumer.entity.Notification;
5 | import com.example.notificationconsumer.service.NotificationService;
6 | import lombok.RequiredArgsConstructor;
7 | import lombok.extern.slf4j.Slf4j;
8 | import org.apache.kafka.clients.consumer.ConsumerRecord;
9 | import org.springframework.kafka.annotation.KafkaListener;
10 | import org.springframework.messaging.handler.annotation.Headers;
11 | import org.springframework.messaging.handler.annotation.Payload;
12 | import org.springframework.stereotype.Component;
13 |
14 |
15 | @Component
16 | @RequiredArgsConstructor
17 | @Slf4j
18 | public class UserCreatedEventConsumer {
19 |
20 | private final NotificationService notificationService;
21 |
22 |
23 | @KafkaListener(topics = "${kafka.topics.user-created.topic}",
24 | groupId = "${kafka.topics.user-created.consumerGroup}",
25 | containerFactory = "concurrentKafkaListenerContainerFactory"
26 | )
27 | public void consumeCreatedUserEvent(@Payload UserCreatedEvent eventData,
28 | @Headers ConsumerRecord consumerRecord) {
29 | log.info("UserCreatedEventConsumer.consumeApprovalRequestResultedEvent consumed EVENT :{} " +
30 | "from partition : {} " +
31 | "with offset : {} " +
32 | "thread : {} " +
33 | "for message key: {}",
34 | eventData, consumerRecord.partition(), consumerRecord.offset(), Thread.currentThread().getName(), consumerRecord.key());
35 |
36 | Notification entity = Notification.EventToNotificationEntity(eventData);
37 |
38 | notificationService.save(entity);
39 |
40 | }
41 |
42 | }
43 |
--------------------------------------------------------------------------------
/notification-consumer/src/main/java/com/example/notificationconsumer/consumers/model/UserCreatedEvent.java:
--------------------------------------------------------------------------------
1 | package com.example.notificationconsumer.consumers.model;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Builder;
5 | import lombok.Getter;
6 | import lombok.NoArgsConstructor;
7 | import lombok.Setter;
8 | import lombok.ToString;
9 |
10 | @Getter
11 | @Setter
12 | @ToString
13 | @NoArgsConstructor
14 | @AllArgsConstructor
15 | @Builder
16 | public class UserCreatedEvent {
17 | private Long id;
18 | private String firstName;
19 | private String lastName;
20 | private String email;
21 | private Boolean status;
22 | }
23 |
--------------------------------------------------------------------------------
/notification-consumer/src/main/java/com/example/notificationconsumer/entity/Notification.java:
--------------------------------------------------------------------------------
1 | package com.example.notificationconsumer.entity;
2 |
3 | import com.example.notificationconsumer.consumers.model.UserCreatedEvent;
4 | import lombok.Builder;
5 | import lombok.Getter;
6 | import lombok.Setter;
7 | import org.springframework.data.annotation.Id;
8 | import org.springframework.data.couchbase.core.mapping.Document;
9 | import org.springframework.data.couchbase.core.mapping.Field;
10 | import org.springframework.data.couchbase.core.mapping.id.GeneratedValue;
11 |
12 | import static org.springframework.data.couchbase.core.mapping.id.GenerationStrategy.UNIQUE;
13 |
14 | @Getter
15 | @Setter
16 | @Document
17 | @Builder
18 | public class Notification {
19 | @Id
20 | @GeneratedValue(strategy = UNIQUE)
21 | private String id;
22 | @Field
23 | private Long userId;
24 | @Field
25 | private String email;
26 | @Field
27 | private Boolean isSend;
28 |
29 |
30 | public static Notification EventToNotificationEntity(UserCreatedEvent event) {
31 | return Notification.builder()
32 | .userId(event.getId())
33 | .email(event.getEmail())
34 | .isSend(Boolean.TRUE)
35 | .build();
36 | }
37 |
38 | }
39 |
--------------------------------------------------------------------------------
/notification-consumer/src/main/java/com/example/notificationconsumer/repository/NotificationRepository.java:
--------------------------------------------------------------------------------
1 | package com.example.notificationconsumer.repository;
2 |
3 | import com.example.notificationconsumer.entity.Notification;
4 | import org.springframework.data.couchbase.repository.CouchbaseRepository;
5 | import org.springframework.stereotype.Repository;
6 |
7 | @Repository
8 | public interface NotificationRepository extends CouchbaseRepository {
9 | }
10 |
--------------------------------------------------------------------------------
/notification-consumer/src/main/java/com/example/notificationconsumer/service/NotificationService.java:
--------------------------------------------------------------------------------
1 | package com.example.notificationconsumer.service;
2 |
3 | import com.example.notificationconsumer.entity.Notification;
4 | import com.example.notificationconsumer.repository.NotificationRepository;
5 | import lombok.RequiredArgsConstructor;
6 | import lombok.extern.slf4j.Slf4j;
7 | import org.springframework.stereotype.Service;
8 |
9 | @Service
10 | @RequiredArgsConstructor
11 | @Slf4j
12 | public class NotificationService {
13 |
14 | private final NotificationRepository notificationRepository;
15 |
16 | public void save(Notification notification) {
17 | Notification savedEntity = notificationRepository.save(notification);
18 | log.info("NotificationService.save saved Id: {}", savedEntity.getId());
19 | }
20 |
21 |
22 | }
23 |
--------------------------------------------------------------------------------
/notification-consumer/src/main/resources/application.yml:
--------------------------------------------------------------------------------
1 | spring:
2 | application:
3 | name: notification_service
4 |
5 | couchbase:
6 | notification-service:
7 | config:
8 | bootstrapHosts: localhost
9 | notificationBucket: notification
10 | notificationBucketUsername: admin
11 | notificationPassword: 123456
12 | queryTimeout: 300
13 | kvTimeout: 5
14 | connectionTimeout: 10
15 |
16 | server:
17 | port: 0
18 |
19 | kafka:
20 | host: localhost:9092
21 | topics:
22 | user-created:
23 | topic: user_service.user_created.0
24 | consumerGroup: ${spring.application.name}-user-created-consumer
25 | replicationFactor: 1
26 | retentionInMs: 604800000
--------------------------------------------------------------------------------
/notification-consumer/src/test/java/com/example/notificationconsumer/NotificationConsumerApplicationTests.java:
--------------------------------------------------------------------------------
1 | package com.example.notificationconsumer;
2 |
3 | import org.junit.jupiter.api.Test;
4 | import org.springframework.boot.test.context.SpringBootTest;
5 |
6 | @SpringBootTest
7 | class NotificationConsumerApplicationTests {
8 |
9 | @Test
10 | void contextLoads() {
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/postman/Kafka-Example.postman_collection.json:
--------------------------------------------------------------------------------
1 | {
2 | "info": {
3 | "_postman_id": "783b7e7d-0bec-475a-92e7-31cd68f9bfe5",
4 | "name": "Kafka-Example",
5 | "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
6 | },
7 | "item": [
8 | {
9 | "name": "create user",
10 | "request": {
11 | "method": "POST",
12 | "header": [],
13 | "body": {
14 | "mode": "raw",
15 | "raw": "{\n\n \"firstName\": \"Muhammed\",\n \"lastName\": \"Sedef\",\n \"email\": \"muhammetsedef34@gmail.com\",\n \"addressText\": \"Küçükçekmece/İstanbul\"\n}",
16 | "options": {
17 | "raw": {
18 | "language": "json"
19 | }
20 | }
21 | },
22 | "url": {
23 | "raw": "http://localhost:8000/api/user/",
24 | "protocol": "http",
25 | "host": [
26 | "localhost"
27 | ],
28 | "port": "8000",
29 | "path": [
30 | "api",
31 | "user",
32 | ""
33 | ]
34 | }
35 | },
36 | "response": []
37 | },
38 | {
39 | "name": "get user detail",
40 | "request": {
41 | "method": "GET",
42 | "header": [],
43 | "url": {
44 | "raw": "http://localhost:8000/api/user/1",
45 | "protocol": "http",
46 | "host": [
47 | "localhost"
48 | ],
49 | "port": "8000",
50 | "path": [
51 | "api",
52 | "user",
53 | "1"
54 | ]
55 | }
56 | },
57 | "response": []
58 | }
59 | ]
60 | }
--------------------------------------------------------------------------------
/user-address-service/.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 |
--------------------------------------------------------------------------------
/user-address-service/.mvn/wrapper/maven-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/muhammedsedef/Kafka-Example/3f0c43cc29d45a14d6c01a410e627dc2b6330cfa/user-address-service/.mvn/wrapper/maven-wrapper.jar
--------------------------------------------------------------------------------
/user-address-service/.mvn/wrapper/maven-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.6/apache-maven-3.8.6-bin.zip
2 | wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar
3 |
--------------------------------------------------------------------------------
/user-address-service/infra-setup/docker-compose.yml:
--------------------------------------------------------------------------------
1 | # Use postgres/example user/password credentials
2 | version: '3.1'
3 |
4 | services:
5 | kafka-example-db:
6 | image: postgres
7 | restart: always
8 | container_name: "kafka-example-db"
9 | ports:
10 | - "5432:5432"
11 | environment:
12 | POSTGRES_PASSWORD: example
13 | POSTGRES_USER: example
14 | POSTGRES_DB: kafka_example
15 | zookeeper:
16 | image: "docker.io/bitnami/zookeeper:3"
17 | ports:
18 | - "2181:2181"
19 | volumes:
20 | - "zookeeper_data:/bitnami"
21 | environment:
22 | - ALLOW_ANONYMOUS_LOGIN=yes
23 | kafka:
24 | image: "docker.io/bitnami/kafka:2-debian-10"
25 | ports:
26 | - "9092:9092"
27 | expose:
28 | - "9093"
29 | volumes:
30 | - "kafka_data:/bitnami"
31 | environment:
32 | - KAFKA_CFG_ZOOKEEPER_CONNECT=zookeeper:2181
33 | - ALLOW_PLAINTEXT_LISTENER=yes
34 | - KAFKA_ADVERTISED_LISTENERS=INSIDE://kafka:9093,OUTSIDE://localhost:9092
35 | - KAFKA_LISTENER_SECURITY_PROTOCOL_MAP=INSIDE:PLAINTEXT,OUTSIDE:PLAINTEXT
36 | - KAFKA_LISTENERS=INSIDE://0.0.0.0:9093,OUTSIDE://0.0.0.0:9092
37 | - KAFKA_INTER_BROKER_LISTENER_NAME=INSIDE
38 | - KAFKA_ZOOKEEPER_CONNECT=zookeeper:2181
39 | depends_on:
40 | - zookeeper
41 | kafka-ui:
42 | image: provectuslabs/kafka-ui
43 | container_name: kafka-ui
44 | ports:
45 | - "9090:8080"
46 | restart: always
47 | environment:
48 | - KAFKA_CLUSTERS_0_NAME=local
49 | - KAFKA_CLUSTERS_0_BOOTSTRAPSERVERS=kafka:9093
50 | - KAFKA_CLUSTERS_0_ZOOKEEPER=localhost:2181
51 |
52 | volumes:
53 | zookeeper_data:
54 | driver: local
55 | kafka_data:
56 | driver: local
--------------------------------------------------------------------------------
/user-address-service/mvnw:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | # ----------------------------------------------------------------------------
3 | # Licensed to the Apache Software Foundation (ASF) under one
4 | # or more contributor license agreements. See the NOTICE file
5 | # distributed with this work for additional information
6 | # regarding copyright ownership. The ASF licenses this file
7 | # to you under the Apache License, Version 2.0 (the
8 | # "License"); you may not use this file except in compliance
9 | # with the License. You may obtain a copy of the License at
10 | #
11 | # https://www.apache.org/licenses/LICENSE-2.0
12 | #
13 | # Unless required by applicable law or agreed to in writing,
14 | # software distributed under the License is distributed on an
15 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 | # KIND, either express or implied. See the License for the
17 | # specific language governing permissions and limitations
18 | # under the License.
19 | # ----------------------------------------------------------------------------
20 |
21 | # ----------------------------------------------------------------------------
22 | # Maven Start Up Batch script
23 | #
24 | # Required ENV vars:
25 | # ------------------
26 | # JAVA_HOME - location of a JDK home dir
27 | #
28 | # Optional ENV vars
29 | # -----------------
30 | # M2_HOME - location of maven2's installed home dir
31 | # MAVEN_OPTS - parameters passed to the Java VM when running Maven
32 | # e.g. to debug Maven itself, use
33 | # set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
34 | # MAVEN_SKIP_RC - flag to disable loading of mavenrc files
35 | # ----------------------------------------------------------------------------
36 |
37 | if [ -z "$MAVEN_SKIP_RC" ] ; then
38 |
39 | if [ -f /usr/local/etc/mavenrc ] ; then
40 | . /usr/local/etc/mavenrc
41 | fi
42 |
43 | if [ -f /etc/mavenrc ] ; then
44 | . /etc/mavenrc
45 | fi
46 |
47 | if [ -f "$HOME/.mavenrc" ] ; then
48 | . "$HOME/.mavenrc"
49 | fi
50 |
51 | fi
52 |
53 | # OS specific support. $var _must_ be set to either true or false.
54 | cygwin=false;
55 | darwin=false;
56 | mingw=false
57 | case "`uname`" in
58 | CYGWIN*) cygwin=true ;;
59 | MINGW*) mingw=true;;
60 | Darwin*) darwin=true
61 | # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
62 | # See https://developer.apple.com/library/mac/qa/qa1170/_index.html
63 | if [ -z "$JAVA_HOME" ]; then
64 | if [ -x "/usr/libexec/java_home" ]; then
65 | export JAVA_HOME="`/usr/libexec/java_home`"
66 | else
67 | export JAVA_HOME="/Library/Java/Home"
68 | fi
69 | fi
70 | ;;
71 | esac
72 |
73 | if [ -z "$JAVA_HOME" ] ; then
74 | if [ -r /etc/gentoo-release ] ; then
75 | JAVA_HOME=`java-config --jre-home`
76 | fi
77 | fi
78 |
79 | if [ -z "$M2_HOME" ] ; then
80 | ## resolve links - $0 may be a link to maven's home
81 | PRG="$0"
82 |
83 | # need this for relative symlinks
84 | while [ -h "$PRG" ] ; do
85 | ls=`ls -ld "$PRG"`
86 | link=`expr "$ls" : '.*-> \(.*\)$'`
87 | if expr "$link" : '/.*' > /dev/null; then
88 | PRG="$link"
89 | else
90 | PRG="`dirname "$PRG"`/$link"
91 | fi
92 | done
93 |
94 | saveddir=`pwd`
95 |
96 | M2_HOME=`dirname "$PRG"`/..
97 |
98 | # make it fully qualified
99 | M2_HOME=`cd "$M2_HOME" && pwd`
100 |
101 | cd "$saveddir"
102 | # echo Using m2 at $M2_HOME
103 | fi
104 |
105 | # For Cygwin, ensure paths are in UNIX format before anything is touched
106 | if $cygwin ; then
107 | [ -n "$M2_HOME" ] &&
108 | M2_HOME=`cygpath --unix "$M2_HOME"`
109 | [ -n "$JAVA_HOME" ] &&
110 | JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
111 | [ -n "$CLASSPATH" ] &&
112 | CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
113 | fi
114 |
115 | # For Mingw, ensure paths are in UNIX format before anything is touched
116 | if $mingw ; then
117 | [ -n "$M2_HOME" ] &&
118 | M2_HOME="`(cd "$M2_HOME"; pwd)`"
119 | [ -n "$JAVA_HOME" ] &&
120 | JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
121 | fi
122 |
123 | if [ -z "$JAVA_HOME" ]; then
124 | javaExecutable="`which javac`"
125 | if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
126 | # readlink(1) is not available as standard on Solaris 10.
127 | readLink=`which readlink`
128 | if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
129 | if $darwin ; then
130 | javaHome="`dirname \"$javaExecutable\"`"
131 | javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
132 | else
133 | javaExecutable="`readlink -f \"$javaExecutable\"`"
134 | fi
135 | javaHome="`dirname \"$javaExecutable\"`"
136 | javaHome=`expr "$javaHome" : '\(.*\)/bin'`
137 | JAVA_HOME="$javaHome"
138 | export JAVA_HOME
139 | fi
140 | fi
141 | fi
142 |
143 | if [ -z "$JAVACMD" ] ; then
144 | if [ -n "$JAVA_HOME" ] ; then
145 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
146 | # IBM's JDK on AIX uses strange locations for the executables
147 | JAVACMD="$JAVA_HOME/jre/sh/java"
148 | else
149 | JAVACMD="$JAVA_HOME/bin/java"
150 | fi
151 | else
152 | JAVACMD="`\\unset -f command; \\command -v java`"
153 | fi
154 | fi
155 |
156 | if [ ! -x "$JAVACMD" ] ; then
157 | echo "Error: JAVA_HOME is not defined correctly." >&2
158 | echo " We cannot execute $JAVACMD" >&2
159 | exit 1
160 | fi
161 |
162 | if [ -z "$JAVA_HOME" ] ; then
163 | echo "Warning: JAVA_HOME environment variable is not set."
164 | fi
165 |
166 | CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
167 |
168 | # traverses directory structure from process work directory to filesystem root
169 | # first directory with .mvn subdirectory is considered project base directory
170 | find_maven_basedir() {
171 |
172 | if [ -z "$1" ]
173 | then
174 | echo "Path not specified to find_maven_basedir"
175 | return 1
176 | fi
177 |
178 | basedir="$1"
179 | wdir="$1"
180 | while [ "$wdir" != '/' ] ; do
181 | if [ -d "$wdir"/.mvn ] ; then
182 | basedir=$wdir
183 | break
184 | fi
185 | # workaround for JBEAP-8937 (on Solaris 10/Sparc)
186 | if [ -d "${wdir}" ]; then
187 | wdir=`cd "$wdir/.."; pwd`
188 | fi
189 | # end of workaround
190 | done
191 | echo "${basedir}"
192 | }
193 |
194 | # concatenates all lines of a file
195 | concat_lines() {
196 | if [ -f "$1" ]; then
197 | echo "$(tr -s '\n' ' ' < "$1")"
198 | fi
199 | }
200 |
201 | BASE_DIR=`find_maven_basedir "$(pwd)"`
202 | if [ -z "$BASE_DIR" ]; then
203 | exit 1;
204 | fi
205 |
206 | ##########################################################################################
207 | # Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
208 | # This allows using the maven wrapper in projects that prohibit checking in binary data.
209 | ##########################################################################################
210 | if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
211 | if [ "$MVNW_VERBOSE" = true ]; then
212 | echo "Found .mvn/wrapper/maven-wrapper.jar"
213 | fi
214 | else
215 | if [ "$MVNW_VERBOSE" = true ]; then
216 | echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
217 | fi
218 | if [ -n "$MVNW_REPOURL" ]; then
219 | jarUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
220 | else
221 | jarUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
222 | fi
223 | while IFS="=" read key value; do
224 | case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
225 | esac
226 | done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
227 | if [ "$MVNW_VERBOSE" = true ]; then
228 | echo "Downloading from: $jarUrl"
229 | fi
230 | wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
231 | if $cygwin; then
232 | wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"`
233 | fi
234 |
235 | if command -v wget > /dev/null; then
236 | if [ "$MVNW_VERBOSE" = true ]; then
237 | echo "Found wget ... using wget"
238 | fi
239 | if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
240 | wget "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
241 | else
242 | wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
243 | fi
244 | elif command -v curl > /dev/null; then
245 | if [ "$MVNW_VERBOSE" = true ]; then
246 | echo "Found curl ... using curl"
247 | fi
248 | if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
249 | curl -o "$wrapperJarPath" "$jarUrl" -f
250 | else
251 | curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f
252 | fi
253 |
254 | else
255 | if [ "$MVNW_VERBOSE" = true ]; then
256 | echo "Falling back to using Java to download"
257 | fi
258 | javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
259 | # For Cygwin, switch paths to Windows format before running javac
260 | if $cygwin; then
261 | javaClass=`cygpath --path --windows "$javaClass"`
262 | fi
263 | if [ -e "$javaClass" ]; then
264 | if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
265 | if [ "$MVNW_VERBOSE" = true ]; then
266 | echo " - Compiling MavenWrapperDownloader.java ..."
267 | fi
268 | # Compiling the Java class
269 | ("$JAVA_HOME/bin/javac" "$javaClass")
270 | fi
271 | if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
272 | # Running the downloader
273 | if [ "$MVNW_VERBOSE" = true ]; then
274 | echo " - Running MavenWrapperDownloader.java ..."
275 | fi
276 | ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
277 | fi
278 | fi
279 | fi
280 | fi
281 | ##########################################################################################
282 | # End of extension
283 | ##########################################################################################
284 |
285 | export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
286 | if [ "$MVNW_VERBOSE" = true ]; then
287 | echo $MAVEN_PROJECTBASEDIR
288 | fi
289 | MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
290 |
291 | # For Cygwin, switch paths to Windows format before running java
292 | if $cygwin; then
293 | [ -n "$M2_HOME" ] &&
294 | M2_HOME=`cygpath --path --windows "$M2_HOME"`
295 | [ -n "$JAVA_HOME" ] &&
296 | JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
297 | [ -n "$CLASSPATH" ] &&
298 | CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
299 | [ -n "$MAVEN_PROJECTBASEDIR" ] &&
300 | MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
301 | fi
302 |
303 | # Provide a "standardized" way to retrieve the CLI args that will
304 | # work with both Windows and non-Windows executions.
305 | MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
306 | export MAVEN_CMD_LINE_ARGS
307 |
308 | WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
309 |
310 | exec "$JAVACMD" \
311 | $MAVEN_OPTS \
312 | $MAVEN_DEBUG_OPTS \
313 | -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
314 | "-Dmaven.home=${M2_HOME}" \
315 | "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
316 | ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
317 |
--------------------------------------------------------------------------------
/user-address-service/mvnw.cmd:
--------------------------------------------------------------------------------
1 | @REM ----------------------------------------------------------------------------
2 | @REM Licensed to the Apache Software Foundation (ASF) under one
3 | @REM or more contributor license agreements. See the NOTICE file
4 | @REM distributed with this work for additional information
5 | @REM regarding copyright ownership. The ASF licenses this file
6 | @REM to you under the Apache License, Version 2.0 (the
7 | @REM "License"); you may not use this file except in compliance
8 | @REM with the License. You may obtain a copy of the License at
9 | @REM
10 | @REM https://www.apache.org/licenses/LICENSE-2.0
11 | @REM
12 | @REM Unless required by applicable law or agreed to in writing,
13 | @REM software distributed under the License is distributed on an
14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | @REM KIND, either express or implied. See the License for the
16 | @REM specific language governing permissions and limitations
17 | @REM under the License.
18 | @REM ----------------------------------------------------------------------------
19 |
20 | @REM ----------------------------------------------------------------------------
21 | @REM Maven Start Up Batch script
22 | @REM
23 | @REM Required ENV vars:
24 | @REM JAVA_HOME - location of a JDK home dir
25 | @REM
26 | @REM Optional ENV vars
27 | @REM M2_HOME - location of maven2's installed home dir
28 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
29 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
30 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
31 | @REM e.g. to debug Maven itself, use
32 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
33 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
34 | @REM ----------------------------------------------------------------------------
35 |
36 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
37 | @echo off
38 | @REM set title of command window
39 | title %0
40 | @REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
41 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
42 |
43 | @REM set %HOME% to equivalent of $HOME
44 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
45 |
46 | @REM Execute a user defined script before this one
47 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
48 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending
49 | if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %*
50 | if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %*
51 | :skipRcPre
52 |
53 | @setlocal
54 |
55 | set ERROR_CODE=0
56 |
57 | @REM To isolate internal variables from possible post scripts, we use another setlocal
58 | @setlocal
59 |
60 | @REM ==== START VALIDATION ====
61 | if not "%JAVA_HOME%" == "" goto OkJHome
62 |
63 | echo.
64 | echo Error: JAVA_HOME not found in your environment. >&2
65 | echo Please set the JAVA_HOME variable in your environment to match the >&2
66 | echo location of your Java installation. >&2
67 | echo.
68 | goto error
69 |
70 | :OkJHome
71 | if exist "%JAVA_HOME%\bin\java.exe" goto init
72 |
73 | echo.
74 | echo Error: JAVA_HOME is set to an invalid directory. >&2
75 | echo JAVA_HOME = "%JAVA_HOME%" >&2
76 | echo Please set the JAVA_HOME variable in your environment to match the >&2
77 | echo location of your Java installation. >&2
78 | echo.
79 | goto error
80 |
81 | @REM ==== END VALIDATION ====
82 |
83 | :init
84 |
85 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
86 | @REM Fallback to current working directory if not found.
87 |
88 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
89 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
90 |
91 | set EXEC_DIR=%CD%
92 | set WDIR=%EXEC_DIR%
93 | :findBaseDir
94 | IF EXIST "%WDIR%"\.mvn goto baseDirFound
95 | cd ..
96 | IF "%WDIR%"=="%CD%" goto baseDirNotFound
97 | set WDIR=%CD%
98 | goto findBaseDir
99 |
100 | :baseDirFound
101 | set MAVEN_PROJECTBASEDIR=%WDIR%
102 | cd "%EXEC_DIR%"
103 | goto endDetectBaseDir
104 |
105 | :baseDirNotFound
106 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
107 | cd "%EXEC_DIR%"
108 |
109 | :endDetectBaseDir
110 |
111 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
112 |
113 | @setlocal EnableExtensions EnableDelayedExpansion
114 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
115 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
116 |
117 | :endReadAdditionalConfig
118 |
119 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
120 | set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
121 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
122 |
123 | set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
124 |
125 | FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
126 | IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
127 | )
128 |
129 | @REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
130 | @REM This allows using the maven wrapper in projects that prohibit checking in binary data.
131 | if exist %WRAPPER_JAR% (
132 | if "%MVNW_VERBOSE%" == "true" (
133 | echo Found %WRAPPER_JAR%
134 | )
135 | ) else (
136 | if not "%MVNW_REPOURL%" == "" (
137 | SET DOWNLOAD_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
138 | )
139 | if "%MVNW_VERBOSE%" == "true" (
140 | echo Couldn't find %WRAPPER_JAR%, downloading it ...
141 | echo Downloading from: %DOWNLOAD_URL%
142 | )
143 |
144 | powershell -Command "&{"^
145 | "$webclient = new-object System.Net.WebClient;"^
146 | "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
147 | "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
148 | "}"^
149 | "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^
150 | "}"
151 | if "%MVNW_VERBOSE%" == "true" (
152 | echo Finished downloading %WRAPPER_JAR%
153 | )
154 | )
155 | @REM End of extension
156 |
157 | @REM Provide a "standardized" way to retrieve the CLI args that will
158 | @REM work with both Windows and non-Windows executions.
159 | set MAVEN_CMD_LINE_ARGS=%*
160 |
161 | %MAVEN_JAVA_EXE% ^
162 | %JVM_CONFIG_MAVEN_PROPS% ^
163 | %MAVEN_OPTS% ^
164 | %MAVEN_DEBUG_OPTS% ^
165 | -classpath %WRAPPER_JAR% ^
166 | "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^
167 | %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
168 | if ERRORLEVEL 1 goto error
169 | goto end
170 |
171 | :error
172 | set ERROR_CODE=1
173 |
174 | :end
175 | @endlocal & set ERROR_CODE=%ERROR_CODE%
176 |
177 | if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost
178 | @REM check for post script, once with legacy .bat ending and once with .cmd ending
179 | if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat"
180 | if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd"
181 | :skipRcPost
182 |
183 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
184 | if "%MAVEN_BATCH_PAUSE%"=="on" pause
185 |
186 | if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE%
187 |
188 | cmd /C exit /B %ERROR_CODE%
189 |
--------------------------------------------------------------------------------
/user-address-service/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | org.springframework.boot
7 | spring-boot-starter-parent
8 | 2.7.5
9 |
10 |
11 | com.example
12 | user-address-service
13 | 0.0.1-SNAPSHOT
14 | user-address-service
15 | user-address-service
16 |
17 | 11
18 |
19 |
20 |
21 | org.springframework.boot
22 | spring-boot-starter-web
23 |
24 |
25 | org.springframework.kafka
26 | spring-kafka
27 |
28 |
29 |
30 | org.springframework.boot
31 | spring-boot-starter-data-jpa
32 |
33 |
34 | org.postgresql
35 | postgresql
36 | runtime
37 |
38 |
39 | org.projectlombok
40 | lombok
41 | true
42 |
43 |
44 | org.springframework.boot
45 | spring-boot-configuration-processor
46 | true
47 |
48 |
49 | org.springframework.boot
50 | spring-boot-starter-test
51 | test
52 |
53 |
54 | org.springframework.kafka
55 | spring-kafka-test
56 | test
57 |
58 |
59 |
60 |
61 |
62 |
63 | org.springframework.boot
64 | spring-boot-maven-plugin
65 |
66 |
67 |
68 | org.projectlombok
69 | lombok
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
--------------------------------------------------------------------------------
/user-address-service/src/main/java/com/example/useraddressservice/UserAddressServiceApplication.java:
--------------------------------------------------------------------------------
1 | package com.example.useraddressservice;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 |
6 | @SpringBootApplication
7 | public class UserAddressServiceApplication {
8 |
9 | public static void main(String[] args) {
10 | SpringApplication.run(UserAddressServiceApplication.class, args);
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/user-address-service/src/main/java/com/example/useraddressservice/consumers/configuration/UserCreatedKafkaConsumerConfiguration.java:
--------------------------------------------------------------------------------
1 | package com.example.useraddressservice.consumers.configuration;
2 |
3 | import lombok.RequiredArgsConstructor;
4 | import org.apache.kafka.clients.consumer.ConsumerConfig;
5 | import org.apache.kafka.common.serialization.StringDeserializer;
6 | import org.springframework.beans.factory.annotation.Value;
7 | import org.springframework.context.annotation.Bean;
8 | import org.springframework.context.annotation.Configuration;
9 | import org.springframework.kafka.config.ConcurrentKafkaListenerContainerFactory;
10 | import org.springframework.kafka.core.ConsumerFactory;
11 | import org.springframework.kafka.core.DefaultKafkaConsumerFactory;
12 | import org.springframework.kafka.support.converter.StringJsonMessageConverter;
13 |
14 | import java.util.HashMap;
15 | import java.util.Map;
16 |
17 | @Configuration
18 | @RequiredArgsConstructor
19 | public class UserCreatedKafkaConsumerConfiguration {
20 |
21 | @Value("${kafka.host}")
22 | private String host;
23 |
24 | public ConsumerFactory consumerFactory() {
25 |
26 | // Creating a Map of string-object pairs
27 | Map config = new HashMap<>();
28 |
29 | // Adding the Configuration
30 | config.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, host);
31 | config.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);
32 | config.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);
33 | //config.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, true);
34 |
35 | return new DefaultKafkaConsumerFactory<>(config);
36 | }
37 |
38 | @Bean
39 | // Creating a Listener
40 | public ConcurrentKafkaListenerContainerFactory concurrentKafkaListenerContainerFactory() {
41 | ConcurrentKafkaListenerContainerFactory factory
42 | = new ConcurrentKafkaListenerContainerFactory<>();
43 | factory.setConsumerFactory(consumerFactory());
44 | factory.setMessageConverter(new StringJsonMessageConverter());
45 | return factory;
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/user-address-service/src/main/java/com/example/useraddressservice/consumers/configuration/properties/UserCreatedConsumerProperties.java:
--------------------------------------------------------------------------------
1 | package com.example.useraddressservice.consumers.configuration.properties;
2 |
3 | import lombok.Getter;
4 | import lombok.Setter;
5 | import org.springframework.boot.context.properties.ConfigurationProperties;
6 | import org.springframework.context.annotation.Configuration;
7 |
8 | @Configuration
9 | @ConfigurationProperties(prefix = "kafka.topics.user-created")
10 | @Getter
11 | @Setter
12 | public class UserCreatedConsumerProperties {
13 | private String topic;
14 | private String consumerGroup;
15 | }
16 |
17 |
18 |
--------------------------------------------------------------------------------
/user-address-service/src/main/java/com/example/useraddressservice/consumers/consumer/UserCreatedEventConsumer.java:
--------------------------------------------------------------------------------
1 | package com.example.useraddressservice.consumers.consumer;
2 |
3 | import com.example.useraddressservice.consumers.model.UserCreatedEvent;
4 | import com.example.useraddressservice.entity.Address;
5 | import com.example.useraddressservice.service.AddressService;
6 | import lombok.RequiredArgsConstructor;
7 | import lombok.extern.slf4j.Slf4j;
8 | import org.apache.kafka.clients.consumer.ConsumerRecord;
9 | import org.springframework.kafka.annotation.KafkaListener;
10 | import org.springframework.messaging.handler.annotation.Headers;
11 | import org.springframework.messaging.handler.annotation.Payload;
12 | import org.springframework.stereotype.Component;
13 |
14 |
15 | @Component
16 | @RequiredArgsConstructor
17 | @Slf4j
18 | public class UserCreatedEventConsumer {
19 |
20 | private final AddressService addressService;
21 |
22 |
23 | @KafkaListener(topics = "${kafka.topics.user-created.topic}",
24 | groupId = "${kafka.topics.user-created.consumerGroup}",
25 | containerFactory = "concurrentKafkaListenerContainerFactory"
26 | )
27 | public void consumeCreatedUserEvent(@Payload UserCreatedEvent eventData,
28 | @Headers ConsumerRecord consumerRecord) {
29 | log.info("UserCreatedEventConsumer.consumeApprovalRequestResultedEvent consumed EVENT :{} " +
30 | "from partition : {} " +
31 | "with offset : {} " +
32 | "thread : {} " +
33 | "for message key: {}",
34 | eventData, consumerRecord.partition(), consumerRecord.offset(), Thread.currentThread().getName(), consumerRecord.key());
35 |
36 | Address entity = UserCreatedEvent.getAddressEntityFromEvent(eventData);
37 |
38 | addressService.save(entity);
39 |
40 | }
41 |
42 | }
43 |
--------------------------------------------------------------------------------
/user-address-service/src/main/java/com/example/useraddressservice/consumers/model/UserCreatedEvent.java:
--------------------------------------------------------------------------------
1 | package com.example.useraddressservice.consumers.model;
2 |
3 | import com.example.useraddressservice.entity.Address;
4 | import lombok.AllArgsConstructor;
5 | import lombok.Builder;
6 | import lombok.Getter;
7 | import lombok.NoArgsConstructor;
8 | import lombok.Setter;
9 | import lombok.ToString;
10 |
11 | @Getter
12 | @Setter
13 | @ToString
14 | @NoArgsConstructor
15 | @AllArgsConstructor
16 | @Builder
17 | public class UserCreatedEvent {
18 | private Long id;
19 | private String addressText;
20 |
21 | public static Address getAddressEntityFromEvent(UserCreatedEvent event) {
22 | return Address.builder()
23 | .userId(event.getId())
24 | .addressText(event.getAddressText())
25 | .build();
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/user-address-service/src/main/java/com/example/useraddressservice/controller/AddressController.java:
--------------------------------------------------------------------------------
1 | package com.example.useraddressservice.controller;
2 |
3 | import com.example.useraddressservice.entity.Address;
4 | import com.example.useraddressservice.service.AddressService;
5 | import lombok.RequiredArgsConstructor;
6 | import org.springframework.web.bind.annotation.GetMapping;
7 | import org.springframework.web.bind.annotation.PathVariable;
8 | import org.springframework.web.bind.annotation.RequestMapping;
9 | import org.springframework.web.bind.annotation.RestController;
10 |
11 | @RestController
12 | @RequiredArgsConstructor
13 | @RequestMapping("/api/address")
14 | public class AddressController {
15 |
16 | private final AddressService addressService;
17 |
18 | @GetMapping("/{userId}")
19 | public Address getAddressByUserId(@PathVariable Long userId) {
20 | return addressService.getAddressByUserId(userId);
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/user-address-service/src/main/java/com/example/useraddressservice/entity/Address.java:
--------------------------------------------------------------------------------
1 | package com.example.useraddressservice.entity;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Builder;
5 | import lombok.Data;
6 | import lombok.NoArgsConstructor;
7 |
8 | import javax.persistence.Column;
9 | import javax.persistence.Entity;
10 | import javax.persistence.GeneratedValue;
11 | import javax.persistence.GenerationType;
12 | import javax.persistence.Id;
13 | import javax.persistence.Table;
14 |
15 | @Entity
16 | @Table(name = "user_address")
17 | @Data
18 | @NoArgsConstructor
19 | @AllArgsConstructor
20 | @Builder
21 | public class Address {
22 | @Id
23 | @Column(name = "id")
24 | @GeneratedValue(strategy = GenerationType.IDENTITY)
25 | private Long id;
26 |
27 | @Column(name = "user_id")
28 | private Long userId;
29 |
30 | @Column(name = "address_text")
31 | private String addressText;
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/user-address-service/src/main/java/com/example/useraddressservice/repository/AddressRepository.java:
--------------------------------------------------------------------------------
1 | package com.example.useraddressservice.repository;
2 |
3 | import com.example.useraddressservice.entity.Address;
4 | import org.springframework.data.jpa.repository.JpaRepository;
5 | import org.springframework.data.jpa.repository.Query;
6 | import org.springframework.data.repository.query.Param;
7 | import org.springframework.stereotype.Repository;
8 |
9 | @Repository
10 | public interface AddressRepository extends JpaRepository {
11 |
12 | @Query(value = "from Address a where a.userId=:userId")
13 | Address findByUserId(@Param("userId") Long userId);
14 | }
15 |
--------------------------------------------------------------------------------
/user-address-service/src/main/java/com/example/useraddressservice/service/AddressService.java:
--------------------------------------------------------------------------------
1 | package com.example.useraddressservice.service;
2 |
3 | import com.example.useraddressservice.entity.Address;
4 | import com.example.useraddressservice.repository.AddressRepository;
5 | import lombok.RequiredArgsConstructor;
6 | import org.springframework.stereotype.Service;
7 |
8 | @Service
9 | @RequiredArgsConstructor
10 | public class AddressService {
11 |
12 | private final AddressRepository addressRepository;
13 |
14 | public Address save(Address address) {
15 | return addressRepository.save(address);
16 | }
17 |
18 | public Address getAddressByUserId(Long userId) {
19 | return addressRepository.findByUserId(userId);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/user-address-service/src/main/resources/application.yml:
--------------------------------------------------------------------------------
1 | spring:
2 | application:
3 | name: address_service
4 | datasource:
5 | username: example
6 | password: example
7 | url: jdbc:postgresql://localhost:5432/kafka_example
8 | jpa:
9 | properties:
10 | hibernate:
11 | dialect: org.hibernate.dialect.PostgreSQLDialect
12 | format_sql: true
13 | show-sql: false
14 | hibernate:
15 | ddl-auto: update
16 |
17 | server:
18 | port: 0
19 |
20 | kafka:
21 | host: localhost:9092
22 | topics:
23 | user-created:
24 | topic: user_service.user_created.0
25 | consumerGroup: ${spring.application.name}-user-created-consumer
26 | replicationFactor: 1
27 | retentionInMs: 604800000
28 |
--------------------------------------------------------------------------------
/user-address-service/src/test/java/com/example/useraddressservice/UserAddressServiceApplicationTests.java:
--------------------------------------------------------------------------------
1 | package com.example.useraddressservice;
2 |
3 | import org.junit.jupiter.api.Test;
4 | import org.springframework.boot.test.context.SpringBootTest;
5 |
6 | @SpringBootTest
7 | class UserAddressServiceApplicationTests {
8 |
9 | @Test
10 | void contextLoads() {
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/user-service/.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 |
--------------------------------------------------------------------------------
/user-service/.mvn/wrapper/maven-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/muhammedsedef/Kafka-Example/3f0c43cc29d45a14d6c01a410e627dc2b6330cfa/user-service/.mvn/wrapper/maven-wrapper.jar
--------------------------------------------------------------------------------
/user-service/.mvn/wrapper/maven-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.6/apache-maven-3.8.6-bin.zip
2 | wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar
3 |
--------------------------------------------------------------------------------
/user-service/infra-setup/docker-compose.yml:
--------------------------------------------------------------------------------
1 | # Use postgres/example user/password credentials
2 | version: '3.1'
3 |
4 | services:
5 | kafka-example-db:
6 | image: postgres
7 | restart: always
8 | container_name: "kafka-example-db"
9 | ports:
10 | - "5432:5432"
11 | environment:
12 | POSTGRES_PASSWORD: example
13 | POSTGRES_USER: example
14 | POSTGRES_DB: kafka_example
15 | zookeeper:
16 | image: "docker.io/bitnami/zookeeper:3"
17 | ports:
18 | - "2181:2181"
19 | volumes:
20 | - "zookeeper_data:/bitnami"
21 | environment:
22 | - ALLOW_ANONYMOUS_LOGIN=yes
23 | kafka:
24 | image: "docker.io/bitnami/kafka:2-debian-10"
25 | ports:
26 | - "9092:9092"
27 | expose:
28 | - "9093"
29 | volumes:
30 | - "kafka_data:/bitnami"
31 | environment:
32 | - KAFKA_CFG_ZOOKEEPER_CONNECT=zookeeper:2181
33 | - ALLOW_PLAINTEXT_LISTENER=yes
34 | - KAFKA_ADVERTISED_LISTENERS=INSIDE://kafka:9093,OUTSIDE://localhost:9092
35 | - KAFKA_LISTENER_SECURITY_PROTOCOL_MAP=INSIDE:PLAINTEXT,OUTSIDE:PLAINTEXT
36 | - KAFKA_LISTENERS=INSIDE://0.0.0.0:9093,OUTSIDE://0.0.0.0:9092
37 | - KAFKA_INTER_BROKER_LISTENER_NAME=INSIDE
38 | - KAFKA_ZOOKEEPER_CONNECT=zookeeper:2181
39 | depends_on:
40 | - zookeeper
41 | kafka-ui:
42 | image: provectuslabs/kafka-ui
43 | container_name: kafka-ui
44 | ports:
45 | - "9090:8080"
46 | restart: always
47 | environment:
48 | - KAFKA_CLUSTERS_0_NAME=local
49 | - KAFKA_CLUSTERS_0_BOOTSTRAPSERVERS=kafka:9093
50 | - KAFKA_CLUSTERS_0_ZOOKEEPER=localhost:2181
51 |
52 | volumes:
53 | zookeeper_data:
54 | driver: local
55 | kafka_data:
56 | driver: local
--------------------------------------------------------------------------------
/user-service/mvnw:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | # ----------------------------------------------------------------------------
3 | # Licensed to the Apache Software Foundation (ASF) under one
4 | # or more contributor license agreements. See the NOTICE file
5 | # distributed with this work for additional information
6 | # regarding copyright ownership. The ASF licenses this file
7 | # to you under the Apache License, Version 2.0 (the
8 | # "License"); you may not use this file except in compliance
9 | # with the License. You may obtain a copy of the License at
10 | #
11 | # https://www.apache.org/licenses/LICENSE-2.0
12 | #
13 | # Unless required by applicable law or agreed to in writing,
14 | # software distributed under the License is distributed on an
15 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 | # KIND, either express or implied. See the License for the
17 | # specific language governing permissions and limitations
18 | # under the License.
19 | # ----------------------------------------------------------------------------
20 |
21 | # ----------------------------------------------------------------------------
22 | # Maven Start Up Batch script
23 | #
24 | # Required ENV vars:
25 | # ------------------
26 | # JAVA_HOME - location of a JDK home dir
27 | #
28 | # Optional ENV vars
29 | # -----------------
30 | # M2_HOME - location of maven2's installed home dir
31 | # MAVEN_OPTS - parameters passed to the Java VM when running Maven
32 | # e.g. to debug Maven itself, use
33 | # set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
34 | # MAVEN_SKIP_RC - flag to disable loading of mavenrc files
35 | # ----------------------------------------------------------------------------
36 |
37 | if [ -z "$MAVEN_SKIP_RC" ] ; then
38 |
39 | if [ -f /usr/local/etc/mavenrc ] ; then
40 | . /usr/local/etc/mavenrc
41 | fi
42 |
43 | if [ -f /etc/mavenrc ] ; then
44 | . /etc/mavenrc
45 | fi
46 |
47 | if [ -f "$HOME/.mavenrc" ] ; then
48 | . "$HOME/.mavenrc"
49 | fi
50 |
51 | fi
52 |
53 | # OS specific support. $var _must_ be set to either true or false.
54 | cygwin=false;
55 | darwin=false;
56 | mingw=false
57 | case "`uname`" in
58 | CYGWIN*) cygwin=true ;;
59 | MINGW*) mingw=true;;
60 | Darwin*) darwin=true
61 | # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
62 | # See https://developer.apple.com/library/mac/qa/qa1170/_index.html
63 | if [ -z "$JAVA_HOME" ]; then
64 | if [ -x "/usr/libexec/java_home" ]; then
65 | export JAVA_HOME="`/usr/libexec/java_home`"
66 | else
67 | export JAVA_HOME="/Library/Java/Home"
68 | fi
69 | fi
70 | ;;
71 | esac
72 |
73 | if [ -z "$JAVA_HOME" ] ; then
74 | if [ -r /etc/gentoo-release ] ; then
75 | JAVA_HOME=`java-config --jre-home`
76 | fi
77 | fi
78 |
79 | if [ -z "$M2_HOME" ] ; then
80 | ## resolve links - $0 may be a link to maven's home
81 | PRG="$0"
82 |
83 | # need this for relative symlinks
84 | while [ -h "$PRG" ] ; do
85 | ls=`ls -ld "$PRG"`
86 | link=`expr "$ls" : '.*-> \(.*\)$'`
87 | if expr "$link" : '/.*' > /dev/null; then
88 | PRG="$link"
89 | else
90 | PRG="`dirname "$PRG"`/$link"
91 | fi
92 | done
93 |
94 | saveddir=`pwd`
95 |
96 | M2_HOME=`dirname "$PRG"`/..
97 |
98 | # make it fully qualified
99 | M2_HOME=`cd "$M2_HOME" && pwd`
100 |
101 | cd "$saveddir"
102 | # echo Using m2 at $M2_HOME
103 | fi
104 |
105 | # For Cygwin, ensure paths are in UNIX format before anything is touched
106 | if $cygwin ; then
107 | [ -n "$M2_HOME" ] &&
108 | M2_HOME=`cygpath --unix "$M2_HOME"`
109 | [ -n "$JAVA_HOME" ] &&
110 | JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
111 | [ -n "$CLASSPATH" ] &&
112 | CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
113 | fi
114 |
115 | # For Mingw, ensure paths are in UNIX format before anything is touched
116 | if $mingw ; then
117 | [ -n "$M2_HOME" ] &&
118 | M2_HOME="`(cd "$M2_HOME"; pwd)`"
119 | [ -n "$JAVA_HOME" ] &&
120 | JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
121 | fi
122 |
123 | if [ -z "$JAVA_HOME" ]; then
124 | javaExecutable="`which javac`"
125 | if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
126 | # readlink(1) is not available as standard on Solaris 10.
127 | readLink=`which readlink`
128 | if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
129 | if $darwin ; then
130 | javaHome="`dirname \"$javaExecutable\"`"
131 | javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
132 | else
133 | javaExecutable="`readlink -f \"$javaExecutable\"`"
134 | fi
135 | javaHome="`dirname \"$javaExecutable\"`"
136 | javaHome=`expr "$javaHome" : '\(.*\)/bin'`
137 | JAVA_HOME="$javaHome"
138 | export JAVA_HOME
139 | fi
140 | fi
141 | fi
142 |
143 | if [ -z "$JAVACMD" ] ; then
144 | if [ -n "$JAVA_HOME" ] ; then
145 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
146 | # IBM's JDK on AIX uses strange locations for the executables
147 | JAVACMD="$JAVA_HOME/jre/sh/java"
148 | else
149 | JAVACMD="$JAVA_HOME/bin/java"
150 | fi
151 | else
152 | JAVACMD="`\\unset -f command; \\command -v java`"
153 | fi
154 | fi
155 |
156 | if [ ! -x "$JAVACMD" ] ; then
157 | echo "Error: JAVA_HOME is not defined correctly." >&2
158 | echo " We cannot execute $JAVACMD" >&2
159 | exit 1
160 | fi
161 |
162 | if [ -z "$JAVA_HOME" ] ; then
163 | echo "Warning: JAVA_HOME environment variable is not set."
164 | fi
165 |
166 | CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
167 |
168 | # traverses directory structure from process work directory to filesystem root
169 | # first directory with .mvn subdirectory is considered project base directory
170 | find_maven_basedir() {
171 |
172 | if [ -z "$1" ]
173 | then
174 | echo "Path not specified to find_maven_basedir"
175 | return 1
176 | fi
177 |
178 | basedir="$1"
179 | wdir="$1"
180 | while [ "$wdir" != '/' ] ; do
181 | if [ -d "$wdir"/.mvn ] ; then
182 | basedir=$wdir
183 | break
184 | fi
185 | # workaround for JBEAP-8937 (on Solaris 10/Sparc)
186 | if [ -d "${wdir}" ]; then
187 | wdir=`cd "$wdir/.."; pwd`
188 | fi
189 | # end of workaround
190 | done
191 | echo "${basedir}"
192 | }
193 |
194 | # concatenates all lines of a file
195 | concat_lines() {
196 | if [ -f "$1" ]; then
197 | echo "$(tr -s '\n' ' ' < "$1")"
198 | fi
199 | }
200 |
201 | BASE_DIR=`find_maven_basedir "$(pwd)"`
202 | if [ -z "$BASE_DIR" ]; then
203 | exit 1;
204 | fi
205 |
206 | ##########################################################################################
207 | # Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
208 | # This allows using the maven wrapper in projects that prohibit checking in binary data.
209 | ##########################################################################################
210 | if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
211 | if [ "$MVNW_VERBOSE" = true ]; then
212 | echo "Found .mvn/wrapper/maven-wrapper.jar"
213 | fi
214 | else
215 | if [ "$MVNW_VERBOSE" = true ]; then
216 | echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
217 | fi
218 | if [ -n "$MVNW_REPOURL" ]; then
219 | jarUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
220 | else
221 | jarUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
222 | fi
223 | while IFS="=" read key value; do
224 | case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
225 | esac
226 | done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
227 | if [ "$MVNW_VERBOSE" = true ]; then
228 | echo "Downloading from: $jarUrl"
229 | fi
230 | wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
231 | if $cygwin; then
232 | wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"`
233 | fi
234 |
235 | if command -v wget > /dev/null; then
236 | if [ "$MVNW_VERBOSE" = true ]; then
237 | echo "Found wget ... using wget"
238 | fi
239 | if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
240 | wget "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
241 | else
242 | wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
243 | fi
244 | elif command -v curl > /dev/null; then
245 | if [ "$MVNW_VERBOSE" = true ]; then
246 | echo "Found curl ... using curl"
247 | fi
248 | if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
249 | curl -o "$wrapperJarPath" "$jarUrl" -f
250 | else
251 | curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f
252 | fi
253 |
254 | else
255 | if [ "$MVNW_VERBOSE" = true ]; then
256 | echo "Falling back to using Java to download"
257 | fi
258 | javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
259 | # For Cygwin, switch paths to Windows format before running javac
260 | if $cygwin; then
261 | javaClass=`cygpath --path --windows "$javaClass"`
262 | fi
263 | if [ -e "$javaClass" ]; then
264 | if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
265 | if [ "$MVNW_VERBOSE" = true ]; then
266 | echo " - Compiling MavenWrapperDownloader.java ..."
267 | fi
268 | # Compiling the Java class
269 | ("$JAVA_HOME/bin/javac" "$javaClass")
270 | fi
271 | if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
272 | # Running the downloader
273 | if [ "$MVNW_VERBOSE" = true ]; then
274 | echo " - Running MavenWrapperDownloader.java ..."
275 | fi
276 | ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
277 | fi
278 | fi
279 | fi
280 | fi
281 | ##########################################################################################
282 | # End of extension
283 | ##########################################################################################
284 |
285 | export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
286 | if [ "$MVNW_VERBOSE" = true ]; then
287 | echo $MAVEN_PROJECTBASEDIR
288 | fi
289 | MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
290 |
291 | # For Cygwin, switch paths to Windows format before running java
292 | if $cygwin; then
293 | [ -n "$M2_HOME" ] &&
294 | M2_HOME=`cygpath --path --windows "$M2_HOME"`
295 | [ -n "$JAVA_HOME" ] &&
296 | JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
297 | [ -n "$CLASSPATH" ] &&
298 | CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
299 | [ -n "$MAVEN_PROJECTBASEDIR" ] &&
300 | MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
301 | fi
302 |
303 | # Provide a "standardized" way to retrieve the CLI args that will
304 | # work with both Windows and non-Windows executions.
305 | MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
306 | export MAVEN_CMD_LINE_ARGS
307 |
308 | WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
309 |
310 | exec "$JAVACMD" \
311 | $MAVEN_OPTS \
312 | $MAVEN_DEBUG_OPTS \
313 | -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
314 | "-Dmaven.home=${M2_HOME}" \
315 | "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
316 | ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
317 |
--------------------------------------------------------------------------------
/user-service/mvnw.cmd:
--------------------------------------------------------------------------------
1 | @REM ----------------------------------------------------------------------------
2 | @REM Licensed to the Apache Software Foundation (ASF) under one
3 | @REM or more contributor license agreements. See the NOTICE file
4 | @REM distributed with this work for additional information
5 | @REM regarding copyright ownership. The ASF licenses this file
6 | @REM to you under the Apache License, Version 2.0 (the
7 | @REM "License"); you may not use this file except in compliance
8 | @REM with the License. You may obtain a copy of the License at
9 | @REM
10 | @REM https://www.apache.org/licenses/LICENSE-2.0
11 | @REM
12 | @REM Unless required by applicable law or agreed to in writing,
13 | @REM software distributed under the License is distributed on an
14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | @REM KIND, either express or implied. See the License for the
16 | @REM specific language governing permissions and limitations
17 | @REM under the License.
18 | @REM ----------------------------------------------------------------------------
19 |
20 | @REM ----------------------------------------------------------------------------
21 | @REM Maven Start Up Batch script
22 | @REM
23 | @REM Required ENV vars:
24 | @REM JAVA_HOME - location of a JDK home dir
25 | @REM
26 | @REM Optional ENV vars
27 | @REM M2_HOME - location of maven2's installed home dir
28 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
29 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
30 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
31 | @REM e.g. to debug Maven itself, use
32 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
33 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
34 | @REM ----------------------------------------------------------------------------
35 |
36 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
37 | @echo off
38 | @REM set title of command window
39 | title %0
40 | @REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
41 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
42 |
43 | @REM set %HOME% to equivalent of $HOME
44 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
45 |
46 | @REM Execute a user defined script before this one
47 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
48 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending
49 | if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %*
50 | if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %*
51 | :skipRcPre
52 |
53 | @setlocal
54 |
55 | set ERROR_CODE=0
56 |
57 | @REM To isolate internal variables from possible post scripts, we use another setlocal
58 | @setlocal
59 |
60 | @REM ==== START VALIDATION ====
61 | if not "%JAVA_HOME%" == "" goto OkJHome
62 |
63 | echo.
64 | echo Error: JAVA_HOME not found in your environment. >&2
65 | echo Please set the JAVA_HOME variable in your environment to match the >&2
66 | echo location of your Java installation. >&2
67 | echo.
68 | goto error
69 |
70 | :OkJHome
71 | if exist "%JAVA_HOME%\bin\java.exe" goto init
72 |
73 | echo.
74 | echo Error: JAVA_HOME is set to an invalid directory. >&2
75 | echo JAVA_HOME = "%JAVA_HOME%" >&2
76 | echo Please set the JAVA_HOME variable in your environment to match the >&2
77 | echo location of your Java installation. >&2
78 | echo.
79 | goto error
80 |
81 | @REM ==== END VALIDATION ====
82 |
83 | :init
84 |
85 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
86 | @REM Fallback to current working directory if not found.
87 |
88 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
89 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
90 |
91 | set EXEC_DIR=%CD%
92 | set WDIR=%EXEC_DIR%
93 | :findBaseDir
94 | IF EXIST "%WDIR%"\.mvn goto baseDirFound
95 | cd ..
96 | IF "%WDIR%"=="%CD%" goto baseDirNotFound
97 | set WDIR=%CD%
98 | goto findBaseDir
99 |
100 | :baseDirFound
101 | set MAVEN_PROJECTBASEDIR=%WDIR%
102 | cd "%EXEC_DIR%"
103 | goto endDetectBaseDir
104 |
105 | :baseDirNotFound
106 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
107 | cd "%EXEC_DIR%"
108 |
109 | :endDetectBaseDir
110 |
111 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
112 |
113 | @setlocal EnableExtensions EnableDelayedExpansion
114 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
115 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
116 |
117 | :endReadAdditionalConfig
118 |
119 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
120 | set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
121 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
122 |
123 | set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
124 |
125 | FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
126 | IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
127 | )
128 |
129 | @REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
130 | @REM This allows using the maven wrapper in projects that prohibit checking in binary data.
131 | if exist %WRAPPER_JAR% (
132 | if "%MVNW_VERBOSE%" == "true" (
133 | echo Found %WRAPPER_JAR%
134 | )
135 | ) else (
136 | if not "%MVNW_REPOURL%" == "" (
137 | SET DOWNLOAD_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
138 | )
139 | if "%MVNW_VERBOSE%" == "true" (
140 | echo Couldn't find %WRAPPER_JAR%, downloading it ...
141 | echo Downloading from: %DOWNLOAD_URL%
142 | )
143 |
144 | powershell -Command "&{"^
145 | "$webclient = new-object System.Net.WebClient;"^
146 | "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
147 | "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
148 | "}"^
149 | "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^
150 | "}"
151 | if "%MVNW_VERBOSE%" == "true" (
152 | echo Finished downloading %WRAPPER_JAR%
153 | )
154 | )
155 | @REM End of extension
156 |
157 | @REM Provide a "standardized" way to retrieve the CLI args that will
158 | @REM work with both Windows and non-Windows executions.
159 | set MAVEN_CMD_LINE_ARGS=%*
160 |
161 | %MAVEN_JAVA_EXE% ^
162 | %JVM_CONFIG_MAVEN_PROPS% ^
163 | %MAVEN_OPTS% ^
164 | %MAVEN_DEBUG_OPTS% ^
165 | -classpath %WRAPPER_JAR% ^
166 | "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^
167 | %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
168 | if ERRORLEVEL 1 goto error
169 | goto end
170 |
171 | :error
172 | set ERROR_CODE=1
173 |
174 | :end
175 | @endlocal & set ERROR_CODE=%ERROR_CODE%
176 |
177 | if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost
178 | @REM check for post script, once with legacy .bat ending and once with .cmd ending
179 | if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat"
180 | if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd"
181 | :skipRcPost
182 |
183 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
184 | if "%MAVEN_BATCH_PAUSE%"=="on" pause
185 |
186 | if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE%
187 |
188 | cmd /C exit /B %ERROR_CODE%
189 |
--------------------------------------------------------------------------------
/user-service/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | org.springframework.boot
7 | spring-boot-starter-parent
8 | 2.7.5
9 |
10 |
11 | com.example
12 | user-service
13 | 0.0.1-SNAPSHOT
14 | user-service
15 | user-service
16 |
17 | 11
18 |
19 |
20 |
21 | org.springframework.boot
22 | spring-boot-starter-web
23 |
24 |
25 | org.springframework.kafka
26 | spring-kafka
27 |
28 |
29 |
30 | org.springframework.boot
31 | spring-boot-starter-data-jpa
32 |
33 |
34 | org.springframework.boot
35 | spring-boot-configuration-processor
36 | true
37 |
38 |
39 | org.postgresql
40 | postgresql
41 | runtime
42 |
43 |
44 | org.projectlombok
45 | lombok
46 | true
47 |
48 |
49 | org.springframework.boot
50 | spring-boot-starter-test
51 | test
52 |
53 |
54 | org.springframework.kafka
55 | spring-kafka-test
56 | test
57 |
58 |
59 |
60 |
61 |
62 |
63 | org.springframework.boot
64 | spring-boot-maven-plugin
65 |
66 |
67 |
68 | org.projectlombok
69 | lombok
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
--------------------------------------------------------------------------------
/user-service/src/main/java/com/example/userservice/UserServiceApplication.java:
--------------------------------------------------------------------------------
1 | package com.example.userservice;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 |
6 | @SpringBootApplication
7 | public class UserServiceApplication {
8 |
9 | public static void main(String[] args) {
10 | SpringApplication.run(UserServiceApplication.class, args);
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/user-service/src/main/java/com/example/userservice/config/kafka/configuration/KafkaProducerConfiguration.java:
--------------------------------------------------------------------------------
1 | package com.example.userservice.config.kafka.configuration;
2 |
3 | import org.apache.kafka.clients.producer.ProducerConfig;
4 | import org.apache.kafka.common.serialization.StringSerializer;
5 | import org.springframework.beans.factory.annotation.Value;
6 | import org.springframework.context.annotation.Bean;
7 | import org.springframework.context.annotation.Configuration;
8 | import org.springframework.kafka.core.DefaultKafkaProducerFactory;
9 | import org.springframework.kafka.core.KafkaTemplate;
10 | import org.springframework.kafka.core.ProducerFactory;
11 | import org.springframework.kafka.support.serializer.JsonSerializer;
12 |
13 | import java.util.HashMap;
14 | import java.util.Map;
15 |
16 | @Configuration
17 | public class KafkaProducerConfiguration {
18 |
19 | @Value("${kafka.host}")
20 | private String kafkaBrokers;
21 |
22 | @Bean
23 | public KafkaTemplate tyKafkaTemplate() {
24 | return new KafkaTemplate<>(producerConfig());
25 | }
26 |
27 | private ProducerFactory producerConfig() {
28 | Map config = new HashMap<>();
29 | config.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, kafkaBrokers);
30 | config.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class);
31 | config.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, JsonSerializer.class);
32 | return new DefaultKafkaProducerFactory<>(config);
33 | }
34 | }
--------------------------------------------------------------------------------
/user-service/src/main/java/com/example/userservice/config/kafka/producer/KafkaProducer.java:
--------------------------------------------------------------------------------
1 | package com.example.userservice.config.kafka.producer;
2 |
3 | import lombok.RequiredArgsConstructor;
4 | import lombok.extern.slf4j.Slf4j;
5 | import org.springframework.kafka.core.KafkaTemplate;
6 | import org.springframework.kafka.support.SendResult;
7 | import org.springframework.messaging.support.GenericMessage;
8 | import org.springframework.stereotype.Component;
9 | import org.springframework.util.concurrent.ListenableFuture;
10 | import org.springframework.util.concurrent.ListenableFutureCallback;
11 |
12 | import java.util.Objects;
13 |
14 |
15 | @Component
16 | @RequiredArgsConstructor
17 | @Slf4j
18 | public class KafkaProducer {
19 |
20 | private final KafkaTemplate kafkaTemplate;
21 |
22 | public void sendMessage(GenericMessage message) {
23 | final ListenableFuture extends SendResult> listenableResult = kafkaTemplate.send(message);
24 |
25 | listenableResult.addCallback(new ListenableFutureCallback>() {
26 | @Override
27 | public void onSuccess(SendResult result) {
28 | if (Objects.isNull(result)) {
29 | log.info("Empty result on success for message {}", message);
30 | return;
31 | }
32 | log.info("Message :{} published, topic : {}, partition : {} and offset : {}", message.getPayload(),
33 | result.getRecordMetadata().topic(),
34 | result.getRecordMetadata().partition(),
35 | result.getRecordMetadata().offset());
36 | }
37 |
38 | @Override
39 | public void onFailure(Throwable ex) {
40 | log.error("Unable to deliver message to kafka", ex);
41 | }
42 | });
43 |
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/user-service/src/main/java/com/example/userservice/config/kafka/properties/UserCreatedTopicProperties.java:
--------------------------------------------------------------------------------
1 | package com.example.userservice.config.kafka.properties;
2 |
3 | import lombok.Getter;
4 | import lombok.Setter;
5 | import org.springframework.boot.context.properties.ConfigurationProperties;
6 | import org.springframework.context.annotation.Configuration;
7 |
8 | @Configuration
9 | @ConfigurationProperties(prefix = "kafka.topics.user-created")
10 | @Getter
11 | @Setter
12 | public class UserCreatedTopicProperties {
13 | private String topicName;
14 | private int partitionCount;
15 | private short replicationFactor;
16 | private String retentionInMs;
17 | }
18 |
--------------------------------------------------------------------------------
/user-service/src/main/java/com/example/userservice/controller/UserController.java:
--------------------------------------------------------------------------------
1 | package com.example.userservice.controller;
2 |
3 | import com.example.userservice.dto.AddressResponseDto;
4 | import com.example.userservice.dto.UserCreateRequest;
5 | import com.example.userservice.dto.UserResponse;
6 | import com.example.userservice.entity.User;
7 | import com.example.userservice.service.UserService;
8 | import lombok.RequiredArgsConstructor;
9 | import org.springframework.http.ResponseEntity;
10 | import org.springframework.web.bind.annotation.GetMapping;
11 | import org.springframework.web.bind.annotation.PathVariable;
12 | import org.springframework.web.bind.annotation.PostMapping;
13 | import org.springframework.web.bind.annotation.RequestBody;
14 | import org.springframework.web.bind.annotation.RequestMapping;
15 | import org.springframework.web.bind.annotation.RestController;
16 | import org.springframework.web.client.RestTemplate;
17 |
18 | @RestController
19 | @RequestMapping("/api/user")
20 | @RequiredArgsConstructor
21 | public class UserController {
22 | private RestTemplate restTemplate = new RestTemplate();
23 | private final UserService userService;
24 |
25 | @PostMapping
26 | public User create(@RequestBody UserCreateRequest userCreateRequest) {
27 | return userService.create(userCreateRequest);
28 | }
29 |
30 | @GetMapping("/{userId}")
31 | public UserResponse getUserAddress(@PathVariable Long userId) {
32 | // You have to change user-address service port according to running port
33 | String url = String.format("http://localhost:8002/api/address/%s", userId);
34 | ResponseEntity address = restTemplate.getForEntity(url, AddressResponseDto.class);
35 |
36 | User user = userService.getUserById(address.getBody().getUserId());
37 | return UserResponse.getUserResponseWithAddress(user, address.getBody());
38 |
39 | }
40 | }
--------------------------------------------------------------------------------
/user-service/src/main/java/com/example/userservice/dto/AddressResponseDto.java:
--------------------------------------------------------------------------------
1 | package com.example.userservice.dto;
2 |
3 | import lombok.Data;
4 | import lombok.NoArgsConstructor;
5 |
6 | @Data
7 | @NoArgsConstructor
8 | public class AddressResponseDto {
9 | private Long id;
10 | private Long userId;
11 | private String addressText;
12 | }
13 |
--------------------------------------------------------------------------------
/user-service/src/main/java/com/example/userservice/dto/BaseResponseDto.java:
--------------------------------------------------------------------------------
1 | package com.example.userservice.dto;
2 |
3 | import lombok.Data;
4 | import lombok.Getter;
5 | import lombok.Setter;
6 |
7 | import java.util.Date;
8 |
9 | @Data
10 | @Getter
11 | @Setter
12 | public class BaseResponseDto {
13 | private Long id;
14 | private Date createdAt;
15 | private Date updatedAt;
16 | }
17 |
--------------------------------------------------------------------------------
/user-service/src/main/java/com/example/userservice/dto/UserCreateRequest.java:
--------------------------------------------------------------------------------
1 | package com.example.userservice.dto;
2 |
3 | import lombok.Data;
4 |
5 | @Data
6 | public class UserCreateRequest {
7 | private String firstName;
8 | private String lastName;
9 | private String email;
10 | private String addressText;
11 | }
12 |
--------------------------------------------------------------------------------
/user-service/src/main/java/com/example/userservice/dto/UserCreatedPayload.java:
--------------------------------------------------------------------------------
1 | package com.example.userservice.dto;
2 |
3 | import com.example.userservice.entity.User;
4 | import lombok.Builder;
5 | import lombok.Data;
6 |
7 | import java.util.Date;
8 |
9 | @Data
10 | @Builder
11 | public class UserCreatedPayload {
12 |
13 | private Long id;
14 | private String firstName;
15 | private String lastName;
16 | private String email;
17 | private String addressText;
18 | private Date createdAt;
19 | private Date updatedAt;
20 | private Boolean status;
21 |
22 | public static UserCreatedPayload GetUserCreatedPayload(User user, String addressText) {
23 | return UserCreatedPayload.builder()
24 | .id(user.getId())
25 | .firstName(user.getFirstName())
26 | .lastName(user.getLastName())
27 | .email(user.getEmail())
28 | .addressText(addressText)
29 | .createdAt(user.getCreatedAt())
30 | .updatedAt(user.getUpdatedAt())
31 | .status(user.getStatus())
32 | .build();
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/user-service/src/main/java/com/example/userservice/dto/UserResponse.java:
--------------------------------------------------------------------------------
1 | package com.example.userservice.dto;
2 |
3 | import com.example.userservice.entity.User;
4 | import lombok.Builder;
5 | import lombok.Data;
6 | import lombok.Getter;
7 | import lombok.Setter;
8 |
9 | @Data
10 | @Getter
11 | @Setter
12 | @Builder
13 | public class UserResponse extends BaseResponseDto {
14 | private String firstName;
15 | private String lastName;
16 | private String email;
17 | private AddressResponseDto address;
18 |
19 | public static UserResponse getUserResponseWithAddress(User user, AddressResponseDto address) {
20 | UserResponse response = UserResponse.builder()
21 | .firstName(user.getFirstName())
22 | .lastName(user.getLastName())
23 | .email(user.getEmail())
24 | .address(address)
25 | .build();
26 | response.setId(user.getId());
27 | response.setCreatedAt(user.getCreatedAt());
28 | response.setCreatedAt(user.getCreatedAt());
29 | return response;
30 |
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/user-service/src/main/java/com/example/userservice/entity/BaseEntity.java:
--------------------------------------------------------------------------------
1 | package com.example.userservice.entity;
2 |
3 | import lombok.Getter;
4 | import lombok.Setter;
5 | import org.hibernate.annotations.CreationTimestamp;
6 | import org.hibernate.annotations.UpdateTimestamp;
7 |
8 | import javax.persistence.Column;
9 | import javax.persistence.MappedSuperclass;
10 | import java.util.Date;
11 |
12 | @Getter
13 | @Setter
14 | @MappedSuperclass
15 | public class BaseEntity {
16 |
17 | @Column(name = "created_at")
18 | //@Temporal(TemporalType.TIMESTAMP)
19 | @CreationTimestamp
20 | private Date createdAt;
21 |
22 | @Column(name = "updated_at")
23 | //@Temporal(TemporalType.TIMESTAMP)
24 | @UpdateTimestamp
25 | private Date updatedAt;
26 |
27 | @Column(name = "status")
28 | private Boolean status = true;
29 | }
--------------------------------------------------------------------------------
/user-service/src/main/java/com/example/userservice/entity/User.java:
--------------------------------------------------------------------------------
1 | package com.example.userservice.entity;
2 |
3 |
4 | import com.example.userservice.dto.UserCreateRequest;
5 | import lombok.AllArgsConstructor;
6 | import lombok.Builder;
7 | import lombok.Data;
8 | import lombok.NoArgsConstructor;
9 |
10 | import javax.persistence.Column;
11 | import javax.persistence.Entity;
12 | import javax.persistence.GeneratedValue;
13 | import javax.persistence.GenerationType;
14 | import javax.persistence.Id;
15 | import javax.persistence.Table;
16 |
17 | @Entity
18 | @Table(name = "users")
19 |
20 | @Data
21 | @NoArgsConstructor
22 | @AllArgsConstructor
23 | @Builder
24 | public class User extends BaseEntity {
25 |
26 | @Id
27 | @Column(name = "id")
28 | @GeneratedValue(strategy = GenerationType.IDENTITY)
29 | private Long id;
30 |
31 | @Column(name = "first_name", nullable = false)
32 | private String firstName;
33 |
34 | @Column(name = "last_name", nullable = false)
35 | private String lastName;
36 |
37 | //unique = true,
38 | @Column(name = "email", nullable = false)
39 | private String email;
40 |
41 | public static User getUser(UserCreateRequest userCreateRequest) {
42 | return User.builder()
43 | .firstName(userCreateRequest.getFirstName())
44 | .lastName(userCreateRequest.getLastName())
45 | .email(userCreateRequest.getEmail())
46 | .build();
47 | }
48 | }
--------------------------------------------------------------------------------
/user-service/src/main/java/com/example/userservice/repository/UserRepository.java:
--------------------------------------------------------------------------------
1 | package com.example.userservice.repository;
2 |
3 | import com.example.userservice.entity.User;
4 | import org.springframework.data.jpa.repository.JpaRepository;
5 | import org.springframework.stereotype.Repository;
6 |
7 | @Repository
8 | public interface UserRepository extends JpaRepository {
9 | }
10 |
--------------------------------------------------------------------------------
/user-service/src/main/java/com/example/userservice/service/UserService.java:
--------------------------------------------------------------------------------
1 | package com.example.userservice.service;
2 |
3 | import com.example.userservice.config.kafka.producer.KafkaProducer;
4 | import com.example.userservice.config.kafka.properties.UserCreatedTopicProperties;
5 | import com.example.userservice.dto.UserCreateRequest;
6 | import com.example.userservice.dto.UserCreatedPayload;
7 | import com.example.userservice.entity.User;
8 | import com.example.userservice.repository.UserRepository;
9 | import lombok.RequiredArgsConstructor;
10 | import org.springframework.messaging.support.GenericMessage;
11 | import org.springframework.stereotype.Service;
12 |
13 | import java.util.HashMap;
14 | import java.util.Map;
15 | import java.util.Optional;
16 |
17 | import static org.springframework.kafka.support.KafkaHeaders.MESSAGE_KEY;
18 | import static org.springframework.kafka.support.KafkaHeaders.TOPIC;
19 |
20 | @Service
21 | @RequiredArgsConstructor
22 | public class UserService {
23 |
24 | private final UserRepository userRepository;
25 |
26 | private final KafkaProducer kafkaProducer;
27 |
28 | private final UserCreatedTopicProperties userCreatedTopicProperties;
29 |
30 | public User create(UserCreateRequest userCreateRequest) {
31 | User user = User.getUser(userCreateRequest);
32 | User savedUser = userRepository.save(user);
33 |
34 | UserCreatedPayload payload = UserCreatedPayload.GetUserCreatedPayload(savedUser, userCreateRequest.getAddressText());
35 |
36 | Map headers = new HashMap<>();
37 | headers.put(TOPIC, userCreatedTopicProperties.getTopicName());
38 | headers.put(MESSAGE_KEY, savedUser.getId().toString());
39 |
40 | kafkaProducer.sendMessage(new GenericMessage<>(payload, headers));
41 | return savedUser;
42 | }
43 |
44 | public User getUserById(Long id) {
45 | Optional userOptional = userRepository.findById(id);
46 | if (!userOptional.isPresent()) {
47 | return null;
48 | }
49 | return userOptional.get();
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/user-service/src/main/resources/application.yml:
--------------------------------------------------------------------------------
1 | spring:
2 | application:
3 | name: user_service
4 | datasource:
5 | username: example
6 | password: example
7 | url: jdbc:postgresql://localhost:5432/kafka_example
8 | jpa:
9 | properties:
10 | hibernate:
11 | dialect: org.hibernate.dialect.PostgreSQLDialect
12 | format_sql: true
13 | show-sql: false
14 | hibernate:
15 | ddl-auto: update
16 |
17 | logging:
18 | level:
19 | root: INFO
20 | #web: DEBUG
21 |
22 | server:
23 | port: 8000
24 |
25 | kafka:
26 | host: localhost:9092
27 | topics:
28 | user-created:
29 | topicName: ${spring.application.name}.user_created.0
30 | partitionCount: 1
31 | replicationFactor: 1
32 | retentionInMs: 604800000
--------------------------------------------------------------------------------
/user-service/src/test/java/com/example/userservice/UserServiceApplicationTests.java:
--------------------------------------------------------------------------------
1 | package com.example.userservice;
2 |
3 | import org.junit.jupiter.api.Test;
4 | import org.springframework.boot.test.context.SpringBootTest;
5 |
6 | @SpringBootTest
7 | class UserServiceApplicationTests {
8 |
9 | @Test
10 | void contextLoads() {
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------