├── .idea
├── .gitignore
├── SpringBootMicroservices.iml
├── codeStyles
│ ├── Project.xml
│ └── codeStyleConfig.xml
├── compiler.xml
├── dataSources.xml
├── encodings.xml
├── jarRepositories.xml
├── misc.xml
├── modules.xml
├── sqldialects.xml
└── vcs.xml
├── .vscode
└── settings.json
├── CloudGateway
├── .gitignore
├── .mvn
│ └── wrapper
│ │ ├── maven-wrapper.jar
│ │ └── maven-wrapper.properties
├── Dockerfile
├── mvnw
├── mvnw.cmd
├── pom.xml
└── src
│ ├── main
│ ├── java
│ │ └── com
│ │ │ └── msbeigi
│ │ │ └── cloudgateway
│ │ │ ├── CloudGatewayApplication.java
│ │ │ ├── controller
│ │ │ ├── AuthenticationController.java
│ │ │ └── FallbackController.java
│ │ │ ├── model
│ │ │ └── AuthenticationResponse.java
│ │ │ └── security
│ │ │ └── OktaOAuth2WebSecurity.java
│ └── resources
│ │ └── application.yaml
│ └── test
│ └── java
│ └── com
│ └── msbeigi
│ └── cloudgateway
│ └── CloudGatewayApplicationTests.java
├── ConfigServer
├── .gitignore
├── .mvn
│ └── wrapper
│ │ ├── maven-wrapper.jar
│ │ └── maven-wrapper.properties
├── Dockerfile
├── mvnw
├── mvnw.cmd
├── pom.xml
└── src
│ ├── main
│ ├── java
│ │ └── com
│ │ │ └── msbeigi
│ │ │ └── configserver
│ │ │ └── ConfigServerApplication.java
│ └── resources
│ │ └── application.yaml
│ └── test
│ └── java
│ └── com
│ └── msbeigi
│ └── configserver
│ └── ConfigServerApplicationTests.java
├── OrderService
├── .gitignore
├── .mvn
│ └── wrapper
│ │ ├── maven-wrapper.jar
│ │ └── maven-wrapper.properties
├── Dockerfile
├── mvnw
├── mvnw.cmd
├── pom.xml
└── src
│ ├── main
│ ├── java
│ │ └── com
│ │ │ └── msbeigi
│ │ │ └── orderservice
│ │ │ ├── OrderServiceApplication.java
│ │ │ ├── config
│ │ │ └── FeignConfig.java
│ │ │ ├── controller
│ │ │ └── OrderController.java
│ │ │ ├── entity
│ │ │ └── Order.java
│ │ │ ├── exception
│ │ │ ├── CustomException.java
│ │ │ └── RestResponseEntityExceptionHandler.java
│ │ │ ├── external
│ │ │ ├── client
│ │ │ │ ├── PaymentService.java
│ │ │ │ └── ProductService.java
│ │ │ ├── decoder
│ │ │ │ └── CustomErrorDecoder.java
│ │ │ ├── intercept
│ │ │ │ ├── OAuthRequestInterceptor.java
│ │ │ │ └── RestTemplateInterceptor.java
│ │ │ ├── request
│ │ │ │ └── PaymentRequest.java
│ │ │ └── response
│ │ │ │ ├── ErrorResponse.java
│ │ │ │ ├── PaymentResponse.java
│ │ │ │ └── ProductResponse.java
│ │ │ ├── model
│ │ │ ├── OrderRequest.java
│ │ │ ├── OrderResponse.java
│ │ │ └── PaymentMode.java
│ │ │ ├── repository
│ │ │ └── OrderRepository.java
│ │ │ ├── security
│ │ │ └── WebSecurityConfig.java
│ │ │ └── services
│ │ │ ├── OrderService.java
│ │ │ └── OrderServiceImpl.java
│ └── resources
│ │ └── application.yaml
│ └── test
│ ├── java
│ └── com
│ │ └── msbeigi
│ │ └── orderservice
│ │ ├── OrderServiceApplicationTests.java
│ │ ├── OrderServiceConfig.java
│ │ ├── TestServiceInstanceListSupplier.java
│ │ ├── controller
│ │ └── OrderControllerTest.java
│ │ └── services
│ │ └── OrderServiceImplTest.java
│ └── resources
│ ├── application.yaml
│ └── mock
│ ├── GetPayment.json
│ └── GetProduct.json
├── PaymentService
├── .gitignore
├── .mvn
│ └── wrapper
│ │ ├── maven-wrapper.jar
│ │ └── maven-wrapper.properties
├── Dockerfile
├── mvnw
├── mvnw.cmd
├── pom.xml
└── src
│ ├── main
│ ├── java
│ │ └── com
│ │ │ └── msbeigi
│ │ │ └── paymentservice
│ │ │ ├── PaymentServiceApplication.java
│ │ │ ├── controller
│ │ │ └── PaymentController.java
│ │ │ ├── entity
│ │ │ └── TransactionDetails.java
│ │ │ ├── model
│ │ │ ├── PaymentMode.java
│ │ │ ├── PaymentRequest.java
│ │ │ └── PaymentResponse.java
│ │ │ ├── repository
│ │ │ └── TransactionsDetailsRepository.java
│ │ │ ├── security
│ │ │ └── WebSecurityConfig.java
│ │ │ └── services
│ │ │ ├── PaymentService.java
│ │ │ └── PaymentServiceImpl.java
│ └── resources
│ │ └── application.yaml
│ └── test
│ └── java
│ └── com
│ └── msbeigi
│ └── paymentservice
│ └── PaymentServiceApplicationTests.java
├── ProductService
├── .gitignore
├── .mvn
│ └── wrapper
│ │ ├── maven-wrapper.jar
│ │ └── maven-wrapper.properties
├── Dockerfile
├── mvnw
├── mvnw.cmd
├── pom.xml
└── src
│ ├── main
│ ├── java
│ │ └── com
│ │ │ └── msbeigi
│ │ │ └── ProductService
│ │ │ ├── ProductServiceApplication.java
│ │ │ ├── controller
│ │ │ └── ProductController.java
│ │ │ ├── entity
│ │ │ └── Product.java
│ │ │ ├── exception
│ │ │ ├── ProductServiceCustomException.java
│ │ │ └── RestResponseEntityExceptionHandler.java
│ │ │ ├── model
│ │ │ ├── ErrorResponse.java
│ │ │ ├── ProductRequest.java
│ │ │ └── ProductResponse.java
│ │ │ ├── repository
│ │ │ └── ProductRepository.java
│ │ │ ├── security
│ │ │ └── WebSecurityConfig.java
│ │ │ └── services
│ │ │ ├── ProductService.java
│ │ │ └── ProductServiceImpl.java
│ └── resources
│ │ └── application.yaml
│ └── test
│ └── java
│ └── com
│ └── msbeigi
│ └── ProductService
│ └── ProductServiceApplicationTests.java
├── README.md
├── ServiceRegistry
├── .gitignore
├── .mvn
│ └── wrapper
│ │ ├── maven-wrapper.jar
│ │ └── maven-wrapper.properties
├── Dockerfile
├── mvnw
├── mvnw.cmd
├── pom.xml
└── src
│ ├── main
│ ├── java
│ │ └── com
│ │ │ └── msbeigi
│ │ │ └── serviceregistry
│ │ │ └── ServiceRegistryApplication.java
│ └── resources
│ │ └── application.yml
│ └── test
│ └── java
│ └── com
│ └── msbeigi
│ └── serviceregistry
│ └── ServiceRegistryApplicationTests.java
├── docker-compose.yml
├── k8s-demo
├── deploy.yml
└── svc.yml
└── k8s
├── cloud-gateway-deployment.yml
├── config-maps.yml
├── config-server-deployment.yml
├── mysql-deployment.yml
├── order-service-deployhment.yml
├── payment-service-deployment.yml
├── product-service-deployment.yml
├── redis-deployment.yml
├── service-registry-statefulset.yml
└── zipkin-deployment.yml
/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /shelf/
3 | /workspace.xml
4 | # Editor-based HTTP Client requests
5 | /httpRequests/
6 | # Datasource local storage ignored files
7 | /dataSources/
8 | /dataSources.local.xml
9 |
--------------------------------------------------------------------------------
/.idea/SpringBootMicroservices.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.idea/codeStyles/Project.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/.idea/codeStyles/codeStyleConfig.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
28 |
29 |
--------------------------------------------------------------------------------
/.idea/dataSources.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | mysql.8
6 | true
7 | com.mysql.cj.jdbc.Driver
8 | jdbc:mysql://localhost:3306
9 | $ProjectFileDir$
10 |
11 |
12 | redis
13 | true
14 | jdbc.RedisDriver
15 | jdbc:redis://localhost:6379/0
16 | $ProjectFileDir$
17 |
18 |
19 |
--------------------------------------------------------------------------------
/.idea/encodings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/.idea/jarRepositories.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.idea/sqldialects.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "yaml.schemas": {
3 | "kubernetes://schema/apps/v1%40deployment": "file:///home/mohsen/Documents/dev/java-projects/SpringBootMicroservices/k8s/payment-service-deployment.yml",
4 | "kubernetes://schema/v1@persistentvolume": "file:///home/mohsen/Documents/dev/java-projects/SpringBootMicroservices/k8s/mysql-deployment.yml"
5 | }
6 | }
--------------------------------------------------------------------------------
/CloudGateway/.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 |
--------------------------------------------------------------------------------
/CloudGateway/.mvn/wrapper/maven-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/msbeigiai/spring-boot-microservices/7c41c629c582ed45a45722b1ec1dba5fbe4574b3/CloudGateway/.mvn/wrapper/maven-wrapper.jar
--------------------------------------------------------------------------------
/CloudGateway/.mvn/wrapper/maven-wrapper.properties:
--------------------------------------------------------------------------------
1 | # Licensed to the Apache Software Foundation (ASF) under one
2 | # or more contributor license agreements. See the NOTICE file
3 | # distributed with this work for additional information
4 | # regarding copyright ownership. The ASF licenses this file
5 | # to you under the Apache License, Version 2.0 (the
6 | # "License"); you may not use this file except in compliance
7 | # with the License. You may obtain a copy of the License at
8 | #
9 | # https://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.7/apache-maven-3.8.7-bin.zip
18 | wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.1/maven-wrapper-3.1.1.jar
19 |
--------------------------------------------------------------------------------
/CloudGateway/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM openjdk:17
2 |
3 | ARG JAR_FILE=target/*.jar
4 |
5 | COPY ${JAR_FILE} cloudgateway.jar
6 |
7 | ENTRYPOINT ["java", "-jar", "/cloudgateway.jar"]
8 |
9 | EXPOSE 9090
10 |
11 |
--------------------------------------------------------------------------------
/CloudGateway/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 |
--------------------------------------------------------------------------------
/CloudGateway/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 |
--------------------------------------------------------------------------------
/CloudGateway/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | org.springframework.boot
7 | spring-boot-starter-parent
8 | 2.7.13
9 |
10 |
11 | com.msbeigi
12 | CloudGateway
13 | 0.0.1
14 | CloudGateway
15 | Demo project for Spring Boot
16 |
17 | 17
18 | 2021.0.7
19 |
20 |
21 |
22 | org.springframework.boot
23 | spring-boot-starter-actuator
24 |
25 |
26 | org.springframework.boot
27 | spring-boot-starter-webflux
28 |
29 |
30 | org.springframework.cloud
31 | spring-cloud-sleuth-zipkin
32 |
33 |
34 | org.springframework.cloud
35 | spring-cloud-starter
36 |
37 |
38 | org.springframework.cloud
39 | spring-cloud-starter-config
40 |
41 |
42 | org.springframework.cloud
43 | spring-cloud-starter-gateway
44 |
45 |
46 | org.springframework.cloud
47 | spring-cloud-starter-netflix-eureka-client
48 |
49 |
50 | org.springframework.cloud
51 | spring-cloud-starter-sleuth
52 |
53 |
54 | org.springframework.cloud
55 | spring-cloud-starter-circuitbreaker-reactor-resilience4j
56 |
57 |
58 | org.springframework.boot
59 | spring-boot-starter-data-redis-reactive
60 |
61 |
62 | org.springframework.boot
63 | spring-boot-starter-security
64 |
65 |
66 | com.okta.spring
67 | okta-spring-boot-starter
68 | 2.1.6
69 |
70 |
71 | org.projectlombok
72 | lombok
73 | true
74 |
75 |
76 | org.springframework.boot
77 | spring-boot-starter-test
78 | test
79 |
80 |
81 | io.projectreactor
82 | reactor-test
83 | test
84 |
85 |
86 |
87 |
88 |
89 |
90 | org.springframework.cloud
91 | spring-cloud-dependencies
92 | ${spring-cloud.version}
93 | pom
94 | import
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 | org.springframework.boot
103 | spring-boot-maven-plugin
104 |
105 |
106 |
107 | org.projectlombok
108 | lombok
109 |
110 |
111 |
112 |
113 |
114 | com.google.cloud.tools
115 | jib-maven-plugin
116 |
117 |
118 | openjdk:17
119 |
120 |
121 | registry.hub.docker.com/msbeigiai/cloudgateway
122 | ${project.version}
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
--------------------------------------------------------------------------------
/CloudGateway/src/main/java/com/msbeigi/cloudgateway/CloudGatewayApplication.java:
--------------------------------------------------------------------------------
1 | package com.msbeigi.cloudgateway;
2 |
3 | import io.github.resilience4j.circuitbreaker.CircuitBreakerConfig;
4 | import org.springframework.boot.SpringApplication;
5 | import org.springframework.boot.autoconfigure.SpringBootApplication;
6 | import org.springframework.cloud.circuitbreaker.resilience4j.Resilience4JCircuitBreakerFactory;
7 | import org.springframework.cloud.circuitbreaker.resilience4j.Resilience4JConfigBuilder;
8 | import org.springframework.cloud.client.circuitbreaker.Customizer;
9 | import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver;
10 | import org.springframework.context.annotation.Bean;
11 | import reactor.core.publisher.Mono;
12 |
13 | @SpringBootApplication
14 | public class CloudGatewayApplication {
15 |
16 | public static void main(String[] args) {
17 | SpringApplication.run(CloudGatewayApplication.class, args);
18 | }
19 |
20 | @Bean
21 | KeyResolver userKeyResolver() {
22 | return exchange -> Mono.just("userKey");
23 | }
24 |
25 | @Bean
26 | public Customizer defaultCustomizer() {
27 | return factory -> factory.configureDefault(
28 | id -> new Resilience4JConfigBuilder(id)
29 | .circuitBreakerConfig(
30 | CircuitBreakerConfig.ofDefaults()
31 | ).build()
32 | );
33 | }
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/CloudGateway/src/main/java/com/msbeigi/cloudgateway/controller/AuthenticationController.java:
--------------------------------------------------------------------------------
1 | package com.msbeigi.cloudgateway.controller;
2 |
3 | import com.msbeigi.cloudgateway.model.AuthenticationResponse;
4 | import org.springframework.http.HttpStatus;
5 | import org.springframework.http.ResponseEntity;
6 | import org.springframework.security.core.GrantedAuthority;
7 | import org.springframework.security.core.annotation.AuthenticationPrincipal;
8 | import org.springframework.security.oauth2.client.OAuth2AuthorizedClient;
9 | import org.springframework.security.oauth2.client.annotation.RegisteredOAuth2AuthorizedClient;
10 | import org.springframework.security.oauth2.core.oidc.user.OidcUser;
11 | import org.springframework.ui.Model;
12 | import org.springframework.web.bind.annotation.GetMapping;
13 | import org.springframework.web.bind.annotation.RequestMapping;
14 | import org.springframework.web.bind.annotation.RestController;
15 |
16 | import java.util.Objects;
17 | import java.util.stream.Collectors;
18 |
19 | @RestController
20 | @RequestMapping("/authenticate")
21 | public class AuthenticationController {
22 |
23 | @GetMapping("/login")
24 | public ResponseEntity login(
25 | @AuthenticationPrincipal OidcUser oidcUser,
26 | Model model,
27 | @RegisteredOAuth2AuthorizedClient("okta") OAuth2AuthorizedClient client
28 | ) {
29 | AuthenticationResponse authenticationResponse =
30 | AuthenticationResponse.builder()
31 | .userId(oidcUser.getEmail())
32 | .accessToken(client.getAccessToken().getTokenValue())
33 | .refreshToken(Objects.requireNonNull(client.getRefreshToken()).getTokenValue())
34 | .expiresAt(Objects.requireNonNull(client.getAccessToken().getExpiresAt()).getEpochSecond())
35 | .authorityList(oidcUser.getAuthorities()
36 | .stream()
37 | .map(GrantedAuthority::getAuthority)
38 | .collect(Collectors.toList()))
39 | .build();
40 | return new ResponseEntity<>(authenticationResponse, HttpStatus.OK);
41 | }
42 |
43 | }
44 |
--------------------------------------------------------------------------------
/CloudGateway/src/main/java/com/msbeigi/cloudgateway/controller/FallbackController.java:
--------------------------------------------------------------------------------
1 | package com.msbeigi.cloudgateway.controller;
2 |
3 | import org.springframework.web.bind.annotation.GetMapping;
4 | import org.springframework.web.bind.annotation.RestController;
5 |
6 | @RestController
7 | public class FallbackController {
8 |
9 | @GetMapping("/orderServiceFallBack")
10 | public String orderServiceFallBack() {
11 | return "Order service is down!";
12 | }
13 |
14 | @GetMapping("/paymentServiceFallBack")
15 | public String paymentServiceFallBack() {
16 | return "Payment service is down!";
17 | }
18 |
19 | @GetMapping("/productServiceFallBack")
20 | public String productServiceFallBack() {
21 | return "Product service is down!";
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/CloudGateway/src/main/java/com/msbeigi/cloudgateway/model/AuthenticationResponse.java:
--------------------------------------------------------------------------------
1 | package com.msbeigi.cloudgateway.model;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Builder;
5 | import lombok.Data;
6 | import lombok.NoArgsConstructor;
7 |
8 | import java.util.Collection;
9 |
10 | @Data
11 | @NoArgsConstructor
12 | @AllArgsConstructor
13 | @Builder
14 | public class AuthenticationResponse {
15 | private String userId;
16 | private String accessToken;
17 | private String refreshToken;
18 | private long expiresAt;
19 | private Collection authorityList;
20 | }
21 |
--------------------------------------------------------------------------------
/CloudGateway/src/main/java/com/msbeigi/cloudgateway/security/OktaOAuth2WebSecurity.java:
--------------------------------------------------------------------------------
1 | package com.msbeigi.cloudgateway.security;
2 |
3 | import org.springframework.context.annotation.Bean;
4 | import org.springframework.context.annotation.Configuration;
5 | import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
6 | import org.springframework.security.config.web.server.ServerHttpSecurity;
7 | import org.springframework.security.web.server.SecurityWebFilterChain;
8 |
9 | @Configuration
10 | @EnableWebFluxSecurity
11 | public class OktaOAuth2WebSecurity {
12 |
13 | @Bean
14 | public SecurityWebFilterChain securityFilterChain(ServerHttpSecurity httpSecurity) {
15 | httpSecurity.authorizeExchange()
16 | .anyExchange()
17 | .authenticated()
18 | .and()
19 | .oauth2Login()
20 | .and()
21 | .oauth2ResourceServer()
22 | .jwt();
23 | return httpSecurity.build();
24 |
25 | }
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/CloudGateway/src/main/resources/application.yaml:
--------------------------------------------------------------------------------
1 | server:
2 | port: 9090
3 |
4 | spring:
5 | redis:
6 | host: redis
7 | port: 6379
8 | application:
9 | name: API-GATEWAY
10 | config:
11 | import: configserver:${CONFIG_SERVER_URL:http://localhost:9296}
12 |
13 | cloud:
14 | gateway:
15 | routes:
16 | - id: ORDER-SERVICE
17 | uri: lb://ORDER-SERVICE
18 | predicates:
19 | - Path=/order/**
20 | filters:
21 | - name: CircuitBreaker
22 | args:
23 | name: ORDER-SERVICE
24 | fallbackuri: forward:/orderServiceFallBack
25 | - name: RequestRateLimiter
26 | args:
27 | redis-rate-limiter.replenishRate: 1
28 | redis-rate-limiter.burstCapacity: 1
29 |
30 | - id: PAYMENT-SERVICE
31 | uri: lb://PAYMENT-SERVICE
32 | predicates:
33 | - Path=/payment/**
34 | filters:
35 | - name: CircuitBreaker
36 | args:
37 | name: PAYMENT-SERVICE
38 | fallbackuri: forward:/paymentServiceFallBack
39 | - name: RequestRateLimiter
40 | args:
41 | redis-rate-limiter.replenishRate: 1
42 | redis-rate-limiter.burstCapacity: 1
43 |
44 | - id: PRODUCT-SERVICE
45 | uri: lb://PRODUCT-SERVICE
46 | predicates:
47 | - Path=/product/**
48 | filters:
49 | - name: CircuitBreaker
50 | args:
51 | name: PRODUCT-SERVICE
52 | fallbackuri: forward:/paymentServiceFallBack
53 | - name: RequestRateLimiter
54 | args:
55 | redis-rate-limiter.replenishRate: 1
56 | redis-rate-limiter.burstCapacity: 1
57 |
58 | okta:
59 | oauth2:
60 | issuer: https://dev-64973606.okta.com/oauth2/default
61 | audience: api://default
62 | client-id: 0oaa4cqbuyzWeNFec5d7
63 | client-secret: 1TQczKd2HajEL74KggFBLI5uKHDexYU5-ybSYKms
64 | scopes: openid, email, profile, offline_access
65 |
--------------------------------------------------------------------------------
/CloudGateway/src/test/java/com/msbeigi/cloudgateway/CloudGatewayApplicationTests.java:
--------------------------------------------------------------------------------
1 | package com.msbeigi.cloudgateway;
2 |
3 | import org.junit.jupiter.api.Test;
4 | import org.springframework.boot.test.context.SpringBootTest;
5 |
6 | @SpringBootTest
7 | class CloudGatewayApplicationTests {
8 |
9 | @Test
10 | void contextLoads() {
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/ConfigServer/.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 |
--------------------------------------------------------------------------------
/ConfigServer/.mvn/wrapper/maven-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/msbeigiai/spring-boot-microservices/7c41c629c582ed45a45722b1ec1dba5fbe4574b3/ConfigServer/.mvn/wrapper/maven-wrapper.jar
--------------------------------------------------------------------------------
/ConfigServer/.mvn/wrapper/maven-wrapper.properties:
--------------------------------------------------------------------------------
1 | # Licensed to the Apache Software Foundation (ASF) under one
2 | # or more contributor license agreements. See the NOTICE file
3 | # distributed with this work for additional information
4 | # regarding copyright ownership. The ASF licenses this file
5 | # to you under the Apache License, Version 2.0 (the
6 | # "License"); you may not use this file except in compliance
7 | # with the License. You may obtain a copy of the License at
8 | #
9 | # https://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.7/apache-maven-3.8.7-bin.zip
18 | wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.1/maven-wrapper-3.1.1.jar
19 |
--------------------------------------------------------------------------------
/ConfigServer/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM openjdk:17
2 |
3 | ARG JAR_FILE=target/*.jar
4 |
5 | COPY ${JAR_FILE} configserver.jar
6 |
7 | ENTRYPOINT ["java", "-jar", "/configserver.jar"]
8 |
9 | EXPOSE 9296
10 |
11 |
--------------------------------------------------------------------------------
/ConfigServer/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 |
--------------------------------------------------------------------------------
/ConfigServer/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 |
--------------------------------------------------------------------------------
/ConfigServer/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | org.springframework.boot
7 | spring-boot-starter-parent
8 | 2.7.13
9 |
10 |
11 | com.msbeigi
12 | ConfigServer
13 | 0.0.1
14 | ConfigServer
15 | Demo project for Spring Boot
16 |
17 | 17
18 | 2021.0.7
19 |
20 |
21 |
22 | org.springframework.cloud
23 | spring-cloud-config-server
24 |
25 |
26 | org.springframework.cloud
27 | spring-cloud-starter-netflix-eureka-client
28 |
29 |
30 |
31 | org.springframework.boot
32 | spring-boot-starter-test
33 | test
34 |
35 |
36 |
37 |
38 |
39 | org.springframework.cloud
40 | spring-cloud-dependencies
41 | ${spring-cloud.version}
42 | pom
43 | import
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 | org.springframework.boot
52 | spring-boot-maven-plugin
53 |
54 |
55 | com.google.cloud.tools
56 | jib-maven-plugin
57 |
58 |
59 | openjdk:17
60 |
61 |
62 | registry.hub.docker.com/msbeigiai/configserver
63 | ${project.version}
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
--------------------------------------------------------------------------------
/ConfigServer/src/main/java/com/msbeigi/configserver/ConfigServerApplication.java:
--------------------------------------------------------------------------------
1 | package com.msbeigi.configserver;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 | import org.springframework.cloud.config.server.EnableConfigServer;
6 |
7 | @SpringBootApplication
8 | @EnableConfigServer
9 | public class ConfigServerApplication {
10 |
11 | public static void main(String[] args) {
12 | SpringApplication.run(ConfigServerApplication.class, args);
13 | }
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/ConfigServer/src/main/resources/application.yaml:
--------------------------------------------------------------------------------
1 | server:
2 | port: 9296
3 |
4 | spring:
5 | application:
6 | name: CONFIG-SERVER
7 | cloud:
8 | config:
9 | server:
10 | git:
11 | uri: https://github.com/msbeigiai/spring-app-config
12 | clone-on-start: true
13 |
14 | eureka:
15 | instance:
16 | prefer-ip-address: true
17 | client:
18 | fetch-registry: true
19 | register-with-eureka: true
20 | service-url:
21 | defaultZone: ${EUREKA_SERVER_ADDRESS:http://localhost:8761/eureka}
22 |
23 |
--------------------------------------------------------------------------------
/ConfigServer/src/test/java/com/msbeigi/configserver/ConfigServerApplicationTests.java:
--------------------------------------------------------------------------------
1 | package com.msbeigi.configserver;
2 |
3 | import org.junit.jupiter.api.Test;
4 | import org.springframework.boot.test.context.SpringBootTest;
5 |
6 | @SpringBootTest
7 | class ConfigServerApplicationTests {
8 |
9 | @Test
10 | void contextLoads() {
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/OrderService/.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 |
--------------------------------------------------------------------------------
/OrderService/.mvn/wrapper/maven-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/msbeigiai/spring-boot-microservices/7c41c629c582ed45a45722b1ec1dba5fbe4574b3/OrderService/.mvn/wrapper/maven-wrapper.jar
--------------------------------------------------------------------------------
/OrderService/.mvn/wrapper/maven-wrapper.properties:
--------------------------------------------------------------------------------
1 | # Licensed to the Apache Software Foundation (ASF) under one
2 | # or more contributor license agreements. See the NOTICE file
3 | # distributed with this work for additional information
4 | # regarding copyright ownership. The ASF licenses this file
5 | # to you under the Apache License, Version 2.0 (the
6 | # "License"); you may not use this file except in compliance
7 | # with the License. You may obtain a copy of the License at
8 | #
9 | # https://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.7/apache-maven-3.8.7-bin.zip
18 | wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.1/maven-wrapper-3.1.1.jar
19 |
--------------------------------------------------------------------------------
/OrderService/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM openjdk:17
2 |
3 | ARG JAR_FILE=target/*.jar
4 |
5 | COPY ${JAR_FILE} orderservice.jar
6 |
7 | ENTRYPOINT ["java", "-jar", "/orderservice.jar"]
8 |
9 | EXPOSE 8082
10 |
11 |
--------------------------------------------------------------------------------
/OrderService/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 |
--------------------------------------------------------------------------------
/OrderService/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | org.springframework.boot
7 | spring-boot-starter-parent
8 | 2.7.12
9 |
10 |
11 | com.msbeigi
12 | OrderService
13 | 0.0.1
14 | OrderService
15 | Demo project for Spring Boot
16 |
17 | 17
18 | 2021.0.7
19 |
20 |
21 |
22 | org.springframework.boot
23 | spring-boot-starter-data-jpa
24 |
25 |
26 | org.springframework.boot
27 | spring-boot-starter-web
28 |
29 |
30 | org.springframework.cloud
31 | spring-cloud-starter
32 |
33 |
34 | org.springframework.cloud
35 | spring-cloud-starter-netflix-eureka-client
36 |
37 |
38 |
39 | com.mysql
40 | mysql-connector-j
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 |
55 | org.springframework.cloud
56 | spring-cloud-starter-config
57 |
58 |
59 |
60 | org.springframework.cloud
61 | spring-cloud-starter-openfeign
62 |
63 |
64 |
65 | org.springframework.cloud
66 | spring-cloud-sleuth-zipkin
67 |
68 |
69 | org.springframework.cloud
70 | spring-cloud-starter-sleuth
71 |
72 |
73 | org.springframework.cloud
74 | spring-cloud-starter-circuitbreaker-reactor-resilience4j
75 |
76 |
77 |
78 | org.springframework.boot
79 | spring-boot-starter-oauth2-client
80 |
81 |
82 | org.springframework.boot
83 | spring-boot-starter-security
84 |
85 |
86 | com.okta.spring
87 | okta-spring-boot-starter
88 | 2.1.6
89 |
90 |
91 | com.github.tomakehurst
92 | wiremock-jre8
93 | 2.35.0
94 | test
95 |
96 |
97 |
98 | com.h2database
99 | h2
100 | runtime
101 |
102 |
103 | org.springframework.security
104 | spring-security-test
105 | test
106 |
107 |
108 |
109 |
110 |
111 | org.springframework.cloud
112 | spring-cloud-dependencies
113 | ${spring-cloud.version}
114 | pom
115 | import
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 | org.springframework.boot
124 | spring-boot-maven-plugin
125 |
126 |
127 |
128 | org.projectlombok
129 | lombok
130 |
131 |
132 |
133 |
134 |
135 | com.google.cloud.tools
136 | jib-maven-plugin
137 |
138 |
139 | openjdk:17
140 |
141 |
142 | registry.hub.docker.com/msbeigiai/orderservice
143 | ${project.version}
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
--------------------------------------------------------------------------------
/OrderService/src/main/java/com/msbeigi/orderservice/OrderServiceApplication.java:
--------------------------------------------------------------------------------
1 | package com.msbeigi.orderservice;
2 |
3 | import com.msbeigi.orderservice.external.intercept.RestTemplateInterceptor;
4 | import org.springframework.beans.factory.annotation.Autowired;
5 | import org.springframework.boot.SpringApplication;
6 | import org.springframework.boot.autoconfigure.SpringBootApplication;
7 | import org.springframework.cloud.client.loadbalancer.LoadBalanced;
8 | import org.springframework.cloud.openfeign.EnableFeignClients;
9 | import org.springframework.context.annotation.Bean;
10 | import org.springframework.security.oauth2.client.OAuth2AuthorizedClientManager;
11 | import org.springframework.security.oauth2.client.OAuth2AuthorizedClientProvider;
12 | import org.springframework.security.oauth2.client.OAuth2AuthorizedClientProviderBuilder;
13 | import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository;
14 | import org.springframework.security.oauth2.client.web.DefaultOAuth2AuthorizedClientManager;
15 | import org.springframework.security.oauth2.client.web.OAuth2AuthorizedClientRepository;
16 | import org.springframework.web.client.RestTemplate;
17 |
18 | import java.util.Arrays;
19 | import java.util.List;
20 |
21 | @SpringBootApplication
22 | @EnableFeignClients
23 | public class OrderServiceApplication {
24 |
25 | public static void main(String[] args) {
26 | SpringApplication.run(OrderServiceApplication.class, args);
27 | }
28 |
29 | @Autowired
30 | private ClientRegistrationRepository clientRegistrationRepository;
31 |
32 | @Autowired
33 | private OAuth2AuthorizedClientRepository oAuth2AuthorizedClientRepository;
34 |
35 | @Bean
36 | @LoadBalanced
37 | public RestTemplate restTemplate() {
38 | RestTemplate restTemplate = new RestTemplate();
39 |
40 | restTemplate.setInterceptors(
41 | Arrays.asList(
42 | new RestTemplateInterceptor(
43 | clientManager(clientRegistrationRepository,
44 | oAuth2AuthorizedClientRepository)
45 | )
46 | )
47 | );
48 | return restTemplate;
49 | }
50 |
51 | @Bean
52 | public OAuth2AuthorizedClientManager clientManager(
53 | ClientRegistrationRepository clientRegistrationRepository,
54 | OAuth2AuthorizedClientRepository oAuth2AuthorizedClientRepository
55 | ) {
56 | OAuth2AuthorizedClientProvider oAuth2AuthorizedClientProvider =
57 | OAuth2AuthorizedClientProviderBuilder
58 | .builder()
59 | .clientCredentials()
60 | .build();
61 | DefaultOAuth2AuthorizedClientManager oAuth2AuthorizedClientManager =
62 | new DefaultOAuth2AuthorizedClientManager(
63 | clientRegistrationRepository,
64 | oAuth2AuthorizedClientRepository
65 | );
66 | oAuth2AuthorizedClientManager.setAuthorizedClientProvider(
67 | oAuth2AuthorizedClientProvider
68 | );
69 |
70 | return oAuth2AuthorizedClientManager;
71 | }
72 |
73 | }
74 |
--------------------------------------------------------------------------------
/OrderService/src/main/java/com/msbeigi/orderservice/config/FeignConfig.java:
--------------------------------------------------------------------------------
1 | package com.msbeigi.orderservice.config;
2 |
3 | import com.msbeigi.orderservice.external.decoder.CustomErrorDecoder;
4 | import feign.codec.ErrorDecoder;
5 | import org.springframework.context.annotation.Bean;
6 | import org.springframework.context.annotation.Configuration;
7 |
8 | @Configuration
9 | public class FeignConfig {
10 |
11 | @Bean
12 | ErrorDecoder errorDecoder() {
13 | return new CustomErrorDecoder();
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/OrderService/src/main/java/com/msbeigi/orderservice/controller/OrderController.java:
--------------------------------------------------------------------------------
1 | package com.msbeigi.orderservice.controller;
2 |
3 | import com.msbeigi.orderservice.model.OrderRequest;
4 | import com.msbeigi.orderservice.model.OrderResponse;
5 | import com.msbeigi.orderservice.services.OrderService;
6 | import lombok.extern.log4j.Log4j2;
7 | import org.springframework.beans.factory.annotation.Autowired;
8 | import org.springframework.http.HttpStatus;
9 | import org.springframework.http.ResponseEntity;
10 | import org.springframework.security.access.prepost.PreAuthorize;
11 | import org.springframework.web.bind.annotation.*;
12 |
13 | @RestController
14 | @RequestMapping("/order")
15 | @Log4j2
16 | public class OrderController {
17 |
18 | @Autowired
19 | private OrderService orderService;
20 |
21 | @PreAuthorize("hasAuthority('Customer')")
22 | @PostMapping("/placeOrder")
23 | public ResponseEntity placeOrder(@RequestBody OrderRequest orderRequest) {
24 | long orderId = orderService.placeOrder(orderRequest);
25 | log.info("Order id has been submitted: {}", orderId);
26 | return new ResponseEntity<>(orderId, HttpStatus.OK);
27 | }
28 |
29 | @PreAuthorize("hasAuthority('Admin') || hasAuthority('Customer')")
30 | @GetMapping("/{orderId}")
31 | public ResponseEntity getOrderDetailsById(@PathVariable long orderId) {
32 | OrderResponse orderResponse =
33 | orderService.getOrderDetailsById(orderId);
34 |
35 | return new ResponseEntity<>(orderResponse, HttpStatus.OK);
36 | }
37 |
38 | }
39 |
--------------------------------------------------------------------------------
/OrderService/src/main/java/com/msbeigi/orderservice/entity/Order.java:
--------------------------------------------------------------------------------
1 | package com.msbeigi.orderservice.entity;
2 |
3 |
4 | import lombok.AllArgsConstructor;
5 | import lombok.Builder;
6 | import lombok.Data;
7 | import lombok.NoArgsConstructor;
8 |
9 | import javax.persistence.*;
10 | import java.time.Instant;
11 |
12 | @Data
13 | @AllArgsConstructor
14 | @NoArgsConstructor
15 | @Builder
16 | @Entity
17 | @Table(name = "order_details")
18 | public class Order {
19 |
20 | @Id
21 | @GeneratedValue(strategy = GenerationType.AUTO)
22 | private long id;
23 |
24 | @Column(name = "product_id")
25 | private long productId;
26 |
27 | @Column(name = "quantity")
28 | private long quantity;
29 |
30 | @Column(name = "order_date")
31 | private Instant orderDate;
32 |
33 | @Column(name = "status")
34 | private String orderStatus;
35 |
36 | @Column(name = "total_amount")
37 | private long amount;
38 | }
39 |
--------------------------------------------------------------------------------
/OrderService/src/main/java/com/msbeigi/orderservice/exception/CustomException.java:
--------------------------------------------------------------------------------
1 | package com.msbeigi.orderservice.exception;
2 |
3 | import lombok.Data;
4 |
5 | @Data
6 | public class CustomException extends RuntimeException {
7 |
8 | private String errorCode;
9 | private int status;
10 |
11 | public CustomException(String message, String errorCode, int status) {
12 | super(message);
13 | this.errorCode = errorCode;
14 | this.status = status;
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/OrderService/src/main/java/com/msbeigi/orderservice/exception/RestResponseEntityExceptionHandler.java:
--------------------------------------------------------------------------------
1 | package com.msbeigi.orderservice.exception;
2 |
3 |
4 | import com.msbeigi.orderservice.external.response.ErrorResponse;
5 | import org.springframework.http.HttpStatus;
6 | import org.springframework.http.ResponseEntity;
7 | import org.springframework.web.bind.annotation.ControllerAdvice;
8 | import org.springframework.web.bind.annotation.ExceptionHandler;
9 | import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
10 |
11 | @ControllerAdvice
12 | public class RestResponseEntityExceptionHandler extends ResponseEntityExceptionHandler {
13 |
14 | @ExceptionHandler(CustomException.class)
15 | public ResponseEntity handleCustomException(CustomException exception) {
16 | return new ResponseEntity<>(ErrorResponse.builder()
17 | .errorMessage(exception.getMessage())
18 | .errorCode(exception.getErrorCode())
19 | .build(),
20 | HttpStatus.valueOf(exception.getStatus()));
21 | }
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/OrderService/src/main/java/com/msbeigi/orderservice/external/client/PaymentService.java:
--------------------------------------------------------------------------------
1 | package com.msbeigi.orderservice.external.client;
2 |
3 | import com.msbeigi.orderservice.exception.CustomException;
4 | import com.msbeigi.orderservice.external.request.PaymentRequest;
5 | import io.github.resilience4j.circuitbreaker.annotation.CircuitBreaker;
6 | import org.springframework.cloud.openfeign.FeignClient;
7 | import org.springframework.http.ResponseEntity;
8 | import org.springframework.web.bind.annotation.PostMapping;
9 | import org.springframework.web.bind.annotation.RequestBody;
10 |
11 | @CircuitBreaker(name = "external", fallbackMethod = "fallback")
12 | @FeignClient(name = "PAYMENT-SERVICE/payment")
13 | public interface PaymentService {
14 | @PostMapping
15 | ResponseEntity doPayment(@RequestBody PaymentRequest paymentRequest);
16 |
17 | default ResponseEntity fallback(Exception e) {
18 | throw new CustomException("Payment service is not available ", "UNAVAILABLE", 500);
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/OrderService/src/main/java/com/msbeigi/orderservice/external/client/ProductService.java:
--------------------------------------------------------------------------------
1 | package com.msbeigi.orderservice.external.client;
2 |
3 | import com.msbeigi.orderservice.exception.CustomException;
4 | import io.github.resilience4j.circuitbreaker.annotation.CircuitBreaker;
5 | import org.springframework.cloud.openfeign.FeignClient;
6 | import org.springframework.http.ResponseEntity;
7 | import org.springframework.web.bind.annotation.PathVariable;
8 | import org.springframework.web.bind.annotation.PutMapping;
9 | import org.springframework.web.bind.annotation.RequestParam;
10 |
11 |
12 | @CircuitBreaker(name = "external", fallbackMethod = "fallback")
13 | @FeignClient(name = "PRODUCT-SERVICE/product")
14 | public interface ProductService {
15 |
16 | @PutMapping("/reduceQuantity/{id}")
17 | ResponseEntity reduceQuantity(
18 | @PathVariable("id") long productId,
19 | @RequestParam long quantity);
20 |
21 | default ResponseEntity fallback(Exception e) {
22 | throw new CustomException("Product service is not available ", "UNAVAILABLE", 500);
23 | }
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/OrderService/src/main/java/com/msbeigi/orderservice/external/decoder/CustomErrorDecoder.java:
--------------------------------------------------------------------------------
1 | package com.msbeigi.orderservice.external.decoder;
2 |
3 | import com.fasterxml.jackson.databind.ObjectMapper;
4 | import com.msbeigi.orderservice.exception.CustomException;
5 | import com.msbeigi.orderservice.external.response.ErrorResponse;
6 | import feign.Response;
7 | import feign.codec.ErrorDecoder;
8 | import lombok.extern.log4j.Log4j2;
9 |
10 | import java.io.IOException;
11 |
12 | @Log4j2
13 | public class CustomErrorDecoder implements ErrorDecoder {
14 |
15 | @Override
16 | public Exception decode(String s, Response response) {
17 | ObjectMapper objectMapper = new ObjectMapper();
18 |
19 | log.info("::{}", response.request().url());
20 | log.info("::{}", response.request().headers());
21 |
22 | try {
23 | ErrorResponse errorResponse =
24 | objectMapper.readValue(response.body().asInputStream(),
25 | ErrorResponse.class);
26 | return new CustomException(errorResponse.getErrorMessage(),
27 | errorResponse.getErrorCode(), response.status());
28 | } catch (IOException e) {
29 | throw new CustomException("Internal Server Error",
30 | "INTERNAL_SERVER_ERROR", 500);
31 | }
32 |
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/OrderService/src/main/java/com/msbeigi/orderservice/external/intercept/OAuthRequestInterceptor.java:
--------------------------------------------------------------------------------
1 | package com.msbeigi.orderservice.external.intercept;
2 |
3 | import feign.RequestInterceptor;
4 | import feign.RequestTemplate;
5 | import org.springframework.beans.factory.annotation.Autowired;
6 | import org.springframework.context.annotation.Configuration;
7 | import org.springframework.security.oauth2.client.OAuth2AuthorizeRequest;
8 | import org.springframework.security.oauth2.client.OAuth2AuthorizedClientManager;
9 |
10 | @Configuration
11 | public class OAuthRequestInterceptor implements RequestInterceptor {
12 |
13 | @Autowired
14 | private OAuth2AuthorizedClientManager oAuth2AuthorizedClientManager;
15 |
16 | @Override
17 | public void apply(RequestTemplate template) {
18 | template.header("Authorization", "Bearer " +
19 | oAuth2AuthorizedClientManager
20 | .authorize(OAuth2AuthorizeRequest
21 | .withClientRegistrationId("internal-client")
22 | .principal("internal")
23 | .build())
24 | .getAccessToken().getTokenValue());
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/OrderService/src/main/java/com/msbeigi/orderservice/external/intercept/RestTemplateInterceptor.java:
--------------------------------------------------------------------------------
1 | package com.msbeigi.orderservice.external.intercept;
2 |
3 | import org.springframework.http.HttpRequest;
4 | import org.springframework.http.client.ClientHttpRequestExecution;
5 | import org.springframework.http.client.ClientHttpRequestInterceptor;
6 | import org.springframework.http.client.ClientHttpResponse;
7 | import org.springframework.security.oauth2.client.OAuth2AuthorizeRequest;
8 | import org.springframework.security.oauth2.client.OAuth2AuthorizedClientManager;
9 |
10 | import java.io.IOException;
11 |
12 | public class RestTemplateInterceptor implements ClientHttpRequestInterceptor {
13 |
14 | private OAuth2AuthorizedClientManager oAuth2AuthorizedClientManager;
15 |
16 | public RestTemplateInterceptor(OAuth2AuthorizedClientManager oAuth2AuthorizedClientManager) {
17 | this.oAuth2AuthorizedClientManager = oAuth2AuthorizedClientManager;
18 | }
19 |
20 | @Override
21 | public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
22 | request.getHeaders()
23 | .add("Authorization", "Bearer " +
24 | oAuth2AuthorizedClientManager
25 | .authorize(OAuth2AuthorizeRequest
26 | .withClientRegistrationId("internal-client")
27 | .principal("internal")
28 | .build())
29 | .getAccessToken()
30 | .getTokenValue());
31 | return execution.execute(request, body);
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/OrderService/src/main/java/com/msbeigi/orderservice/external/request/PaymentRequest.java:
--------------------------------------------------------------------------------
1 | package com.msbeigi.orderservice.external.request;
2 |
3 | import com.msbeigi.orderservice.model.PaymentMode;
4 | import lombok.AllArgsConstructor;
5 | import lombok.Builder;
6 | import lombok.Data;
7 | import lombok.NoArgsConstructor;
8 |
9 | @Data
10 | @NoArgsConstructor
11 | @AllArgsConstructor
12 | @Builder
13 | public class PaymentRequest {
14 |
15 | private long orderId;
16 | private long amount;
17 | private String referenceNumber;
18 | private PaymentMode paymentMode;
19 | }
20 |
--------------------------------------------------------------------------------
/OrderService/src/main/java/com/msbeigi/orderservice/external/response/ErrorResponse.java:
--------------------------------------------------------------------------------
1 | package com.msbeigi.orderservice.external.response;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Builder;
5 | import lombok.Data;
6 | import lombok.NoArgsConstructor;
7 |
8 | @Data
9 | @AllArgsConstructor
10 | @NoArgsConstructor
11 | @Builder
12 | public class ErrorResponse {
13 |
14 | private String errorMessage;
15 | private String errorCode;
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/OrderService/src/main/java/com/msbeigi/orderservice/external/response/PaymentResponse.java:
--------------------------------------------------------------------------------
1 | package com.msbeigi.orderservice.external.response;
2 |
3 | import com.msbeigi.orderservice.model.PaymentMode;
4 | import lombok.AllArgsConstructor;
5 | import lombok.Builder;
6 | import lombok.Data;
7 | import lombok.NoArgsConstructor;
8 |
9 | import java.time.Instant;
10 |
11 | @Data
12 | @AllArgsConstructor
13 | @NoArgsConstructor
14 | @Builder
15 | public class PaymentResponse {
16 | private long paymentId;
17 | private String status;
18 | private PaymentMode paymentMode;
19 | private long amount;
20 | private Instant paymentDate;
21 | private long orderId;
22 | }
23 |
--------------------------------------------------------------------------------
/OrderService/src/main/java/com/msbeigi/orderservice/external/response/ProductResponse.java:
--------------------------------------------------------------------------------
1 | package com.msbeigi.orderservice.external.response;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Builder;
5 | import lombok.Data;
6 | import lombok.NoArgsConstructor;
7 |
8 | @Data
9 | @AllArgsConstructor
10 | @NoArgsConstructor
11 | @Builder
12 | public class ProductResponse {
13 | private long productId;
14 | private String productName;
15 | private long quantity;
16 | private long price;
17 | }
18 |
--------------------------------------------------------------------------------
/OrderService/src/main/java/com/msbeigi/orderservice/model/OrderRequest.java:
--------------------------------------------------------------------------------
1 | package com.msbeigi.orderservice.model;
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 java.time.Instant;
10 |
11 | @Data
12 | @AllArgsConstructor
13 | @NoArgsConstructor
14 | @Builder
15 | public class OrderRequest {
16 | private long productId;
17 | private long totalAmount;
18 | private long quantity;
19 | private PaymentMode paymentMode;
20 | }
21 |
--------------------------------------------------------------------------------
/OrderService/src/main/java/com/msbeigi/orderservice/model/OrderResponse.java:
--------------------------------------------------------------------------------
1 | package com.msbeigi.orderservice.model;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Builder;
5 | import lombok.Data;
6 | import lombok.NoArgsConstructor;
7 |
8 | import java.time.Instant;
9 |
10 | @Data
11 | @AllArgsConstructor
12 | @NoArgsConstructor
13 | @Builder
14 | public class OrderResponse {
15 | private long orderId;
16 | private Instant orderDate;
17 | private String orderStatus;
18 | private long amount;
19 | private ProductDetails productDetails;
20 | private PaymentDetails paymentDetails;
21 |
22 | @Data
23 | @AllArgsConstructor
24 | @NoArgsConstructor
25 | @Builder
26 | public static class ProductDetails {
27 | private long productId;
28 | private String productName;
29 | private long quantity;
30 | private long price;
31 | }
32 |
33 | @Data
34 | @AllArgsConstructor
35 | @NoArgsConstructor
36 | @Builder
37 | public static class PaymentDetails {
38 | private long paymentId;
39 | private PaymentMode paymentMode;
40 | private String paymentStatus;
41 | private Instant paymentDate;
42 | }
43 |
44 | }
45 |
--------------------------------------------------------------------------------
/OrderService/src/main/java/com/msbeigi/orderservice/model/PaymentMode.java:
--------------------------------------------------------------------------------
1 | package com.msbeigi.orderservice.model;
2 |
3 | public enum PaymentMode {
4 | CASH,
5 | PAYPAL,
6 | DEBIT_CARD,
7 | CREDIT_CARD,
8 | APPLE_PAY
9 | }
10 |
--------------------------------------------------------------------------------
/OrderService/src/main/java/com/msbeigi/orderservice/repository/OrderRepository.java:
--------------------------------------------------------------------------------
1 | package com.msbeigi.orderservice.repository;
2 |
3 | import com.msbeigi.orderservice.entity.Order;
4 | import org.springframework.data.jpa.repository.JpaRepository;
5 | import org.springframework.stereotype.Repository;
6 |
7 | @Repository
8 | public interface OrderRepository extends JpaRepository {
9 | }
10 |
--------------------------------------------------------------------------------
/OrderService/src/main/java/com/msbeigi/orderservice/security/WebSecurityConfig.java:
--------------------------------------------------------------------------------
1 | package com.msbeigi.orderservice.security;
2 |
3 | import org.springframework.context.annotation.Bean;
4 | import org.springframework.context.annotation.Configuration;
5 | import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
6 | import org.springframework.security.config.annotation.web.builders.HttpSecurity;
7 | import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
8 | import org.springframework.security.config.annotation.web.configurers.oauth2.server.resource.OAuth2ResourceServerConfigurer;
9 | import org.springframework.security.web.SecurityFilterChain;
10 |
11 | @Configuration
12 | @EnableWebSecurity
13 | @EnableGlobalMethodSecurity(prePostEnabled = true)
14 | public class WebSecurityConfig {
15 |
16 | @Bean
17 | public SecurityFilterChain securityWebFilterChain(HttpSecurity httpSecurity) throws Exception {
18 | httpSecurity
19 | .authorizeRequests(authorizeRequest -> authorizeRequest
20 | .anyRequest()
21 | .authenticated()
22 | )
23 | .oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt);
24 |
25 | return httpSecurity.build();
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/OrderService/src/main/java/com/msbeigi/orderservice/services/OrderService.java:
--------------------------------------------------------------------------------
1 | package com.msbeigi.orderservice.services;
2 |
3 | import com.msbeigi.orderservice.model.OrderRequest;
4 | import com.msbeigi.orderservice.model.OrderResponse;
5 |
6 | public interface OrderService {
7 | long placeOrder(OrderRequest orderRequest);
8 |
9 | OrderResponse getOrderDetailsById(long orderId);
10 | }
11 |
--------------------------------------------------------------------------------
/OrderService/src/main/java/com/msbeigi/orderservice/services/OrderServiceImpl.java:
--------------------------------------------------------------------------------
1 | package com.msbeigi.orderservice.services;
2 |
3 | import com.msbeigi.orderservice.entity.Order;
4 | import com.msbeigi.orderservice.exception.CustomException;
5 | import com.msbeigi.orderservice.external.client.PaymentService;
6 | import com.msbeigi.orderservice.external.client.ProductService;
7 | import com.msbeigi.orderservice.external.request.PaymentRequest;
8 | import com.msbeigi.orderservice.external.response.PaymentResponse;
9 | import com.msbeigi.orderservice.model.OrderRequest;
10 | import com.msbeigi.orderservice.model.OrderResponse;
11 | import com.msbeigi.orderservice.external.response.ProductResponse;
12 | import com.msbeigi.orderservice.repository.OrderRepository;
13 | import lombok.extern.log4j.Log4j2;
14 | import org.springframework.beans.factory.annotation.Autowired;
15 | import org.springframework.http.HttpStatus;
16 | import org.springframework.stereotype.Service;
17 | import org.springframework.web.client.RestTemplate;
18 |
19 | import java.time.Instant;
20 |
21 | @Service
22 | @Log4j2
23 | public class OrderServiceImpl implements OrderService {
24 |
25 | @Autowired
26 | private OrderRepository orderRepository;
27 |
28 | @Autowired
29 | private ProductService productService;
30 |
31 | @Autowired
32 | private PaymentService paymentService;
33 |
34 | @Autowired
35 | private RestTemplate restTemplate;
36 |
37 | @Override
38 | public long placeOrder(OrderRequest orderRequest) {
39 |
40 | log.info("Placing order request: {}", orderRequest);
41 |
42 | productService.reduceQuantity(orderRequest.getProductId(), orderRequest.getQuantity());
43 |
44 | log.info("Creating order with status CREATED!");
45 | Order order = Order.builder()
46 | .amount(orderRequest.getTotalAmount())
47 | .orderStatus("CREATED")
48 | .productId(orderRequest.getProductId())
49 | .orderDate(Instant.now())
50 | .quantity(orderRequest.getQuantity())
51 | .build();
52 | order = orderRepository.save(order);
53 |
54 | log.info("Calling payment service to complete the payment!");
55 |
56 | PaymentRequest paymentRequest =
57 | PaymentRequest.builder()
58 | .orderId(order.getId())
59 | .paymentMode(orderRequest.getPaymentMode())
60 | .amount(orderRequest.getTotalAmount())
61 | .build();
62 |
63 | String orderStatus = null;
64 |
65 | try {
66 | paymentService.doPayment(paymentRequest);
67 | log.info("Payment done successfully, Changing order status!");
68 | orderStatus = "PLACED";
69 | } catch (Exception e) {
70 | log.error("Error occured in payment. Changing order status to PAYMENT_FAILED");
71 | orderStatus = "PAYMENT_FAILED";
72 | }
73 |
74 | order.setOrderStatus(orderStatus);
75 | orderRepository.save(order);
76 |
77 | log.info("Order places successfully with order id: {}", order.getId());
78 |
79 | //BeanUtils.copyProperties(orderRequest, );
80 | return order.getId();
81 | }
82 |
83 | @Override
84 | public OrderResponse getOrderDetailsById(long orderId) {
85 |
86 | log.info("Get order details for order id {}", orderId);
87 |
88 | Order order = orderRepository.findById(orderId)
89 | .orElseThrow(() ->
90 | new CustomException("Order with id " + orderId +
91 | " not found!", "NOT_FOUND", HttpStatus.NOT_FOUND.value()));
92 |
93 | log.info("Invoking product service to fetch the product id: {}", order.getProductId());
94 | ProductResponse productResponse =
95 | restTemplate.getForObject("http://PRODUCT-SERVICE/product/" + order.getProductId(),
96 | ProductResponse.class);
97 |
98 | OrderResponse.ProductDetails productDetails =
99 | OrderResponse.ProductDetails
100 | .builder()
101 | .productName(productResponse.getProductName())
102 | .productId(productResponse.getProductId())
103 | .build();
104 |
105 | log.info("Getting payment information from payment service");
106 | PaymentResponse paymentResponse =
107 | restTemplate.getForObject("http://PAYMENT-SERVICE/payment/order/" + order.getId(),
108 | PaymentResponse.class);
109 | OrderResponse.PaymentDetails paymentDetails =
110 | OrderResponse.PaymentDetails
111 | .builder()
112 | .paymentId(paymentResponse.getPaymentId())
113 | .paymentStatus(paymentResponse.getStatus())
114 | .paymentDate(paymentResponse.getPaymentDate())
115 | .paymentMode(paymentResponse.getPaymentMode())
116 | .build();
117 |
118 |
119 | log.info("Getting order details for order id {}", orderId);
120 |
121 | return OrderResponse.builder()
122 | .orderStatus(order.getOrderStatus())
123 | .orderDate(order.getOrderDate())
124 | .orderId(order.getId())
125 | .amount(order.getAmount())
126 | .productDetails(productDetails)
127 | .paymentDetails(paymentDetails)
128 | .build();
129 |
130 | }
131 | }
132 |
--------------------------------------------------------------------------------
/OrderService/src/main/resources/application.yaml:
--------------------------------------------------------------------------------
1 | server:
2 | port: 8082
3 |
4 | spring:
5 | datasource:
6 | url: jdbc:mysql://${DB_HOST:localhost}:3306/order_db
7 | username: root
8 | password: root
9 | driverClassName: com.mysql.cj.jdbc.Driver
10 | jpa:
11 | database-platform: org.hibernate.dialect.MySQL57InnoDBDialect
12 | hibernate:
13 | ddl-auto: update
14 | application:
15 | name: ORDER-SERVICE
16 |
17 | config:
18 | import: configserver:${CONFIG_SERVER_URL:http://localhost:9296}
19 |
20 | security:
21 | oauth2:
22 | resourceserver:
23 | jwt:
24 | issuer-uri: https://dev-64973606.okta.com/oauth2/default
25 | client:
26 | registration:
27 | internal-client:
28 | provider: okta
29 | authorization-grant-type: client_credentials
30 | scope: internal
31 | client-id: 0oaa4cqbuyzWeNFec5d7
32 | client-secret: 1TQczKd2HajEL74KggFBLI5uKHDexYU5-ybSYKms
33 | provider:
34 | okta:
35 | issuer-uri: https://dev-64973606.okta.com/oauth2/default
36 |
37 | resilience4j:
38 | circuitbreaker:
39 | instances:
40 | external:
41 | event-consumer-buffer-size: 10
42 | failure-rate-threshold: 50
43 | minimum-number-of-calls: 5
44 | automatic-transition-from-open-to-half-open-enabled: true
45 | wait-duration-in-open-state: 5s
46 | permitted-number-of-calls-in-half-open-state: 3
47 | sliding-window-size: 10
48 | sliding-window-type: COUNT_BASED
49 |
50 | #eureka:
51 | # instance:
52 | # prefer-ip-address: true
53 | # client:
54 | # fetch-registry: true
55 | # register-with-eureka: true
56 | # service-url:
57 | # defaultZone: ${EUREKA_SERVER_ADDRESS:http://localhost:8761/eureka}
58 |
--------------------------------------------------------------------------------
/OrderService/src/test/java/com/msbeigi/orderservice/OrderServiceApplicationTests.java:
--------------------------------------------------------------------------------
1 | package com.msbeigi.orderservice;
2 |
3 | import org.junit.jupiter.api.Test;
4 | import org.springframework.boot.test.context.SpringBootTest;
5 |
6 | @SpringBootTest
7 | class OrderServiceApplicationTests {
8 |
9 | @Test
10 | void contextLoads() {
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/OrderService/src/test/java/com/msbeigi/orderservice/OrderServiceConfig.java:
--------------------------------------------------------------------------------
1 | package com.msbeigi.orderservice;
2 |
3 | import org.springframework.boot.test.context.TestConfiguration;
4 | import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier;
5 | import org.springframework.context.annotation.Bean;
6 |
7 | @TestConfiguration
8 | public class OrderServiceConfig {
9 |
10 | @Bean
11 | public ServiceInstanceListSupplier supplier() {
12 | return new TestServiceInstanceListSupplier();
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/OrderService/src/test/java/com/msbeigi/orderservice/TestServiceInstanceListSupplier.java:
--------------------------------------------------------------------------------
1 | package com.msbeigi.orderservice;
2 |
3 | import org.springframework.cloud.client.DefaultServiceInstance;
4 | import org.springframework.cloud.client.ServiceInstance;
5 | import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier;
6 | import reactor.core.publisher.Flux;
7 |
8 | import java.util.ArrayList;
9 | import java.util.List;
10 |
11 | public class TestServiceInstanceListSupplier implements ServiceInstanceListSupplier {
12 | @Override
13 | public String getServiceId() {
14 | return null;
15 | }
16 |
17 | @Override
18 | public Flux> get() {
19 | List result = new ArrayList<>();
20 | result.add(new DefaultServiceInstance(
21 | "PAYMENT-SERVICE",
22 | "PAYMENT-SERVICE",
23 | "localhost",
24 | 8088,
25 | false
26 | ));
27 | result.add(new DefaultServiceInstance(
28 | "PRODUCT-SERVICE",
29 | "PRODUCT-SERVICE",
30 | "localhost",
31 | 8088,
32 | false
33 | ));
34 |
35 | return Flux.just(result);
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/OrderService/src/test/java/com/msbeigi/orderservice/controller/OrderControllerTest.java:
--------------------------------------------------------------------------------
1 | package com.msbeigi.orderservice.controller;
2 |
3 |
4 | import com.fasterxml.jackson.databind.DeserializationFeature;
5 | import com.fasterxml.jackson.databind.ObjectMapper;
6 | import com.fasterxml.jackson.databind.SerializationFeature;
7 | import com.github.tomakehurst.wiremock.core.WireMockConfiguration;
8 | import com.github.tomakehurst.wiremock.junit5.WireMockExtension;
9 | import com.msbeigi.orderservice.OrderServiceConfig;
10 | import com.msbeigi.orderservice.entity.Order;
11 | import com.msbeigi.orderservice.model.OrderRequest;
12 | import com.msbeigi.orderservice.model.OrderResponse;
13 | import com.msbeigi.orderservice.model.PaymentMode;
14 | import com.msbeigi.orderservice.repository.OrderRepository;
15 | import com.msbeigi.orderservice.services.OrderService;
16 | import io.github.resilience4j.circuitbreaker.CircuitBreakerRegistry;
17 | import org.junit.jupiter.api.BeforeEach;
18 | import org.junit.jupiter.api.Test;
19 | import org.junit.jupiter.api.extension.RegisterExtension;
20 | import org.springframework.beans.factory.annotation.Autowired;
21 | import org.springframework.boot.context.properties.EnableConfigurationProperties;
22 | import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
23 | import org.springframework.boot.test.context.SpringBootTest;
24 | import org.springframework.http.HttpStatus;
25 | import org.springframework.http.MediaType;
26 | import org.springframework.security.core.authority.SimpleGrantedAuthority;
27 | import org.springframework.test.context.ContextConfiguration;
28 | import org.springframework.test.web.servlet.MockMvc;
29 | import org.springframework.test.web.servlet.MvcResult;
30 | import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
31 | import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
32 |
33 | import java.io.IOException;
34 | import java.util.Optional;
35 |
36 | import static com.github.tomakehurst.wiremock.client.WireMock.*;
37 | import static java.nio.charset.Charset.defaultCharset;
38 | import static org.junit.jupiter.api.Assertions.assertEquals;
39 | import static org.junit.jupiter.api.Assertions.assertTrue;
40 | import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.jwt;
41 | import static org.springframework.util.StreamUtils.copyToString;
42 |
43 | @SpringBootTest({"server.port=0"})
44 | @EnableConfigurationProperties
45 | @AutoConfigureMockMvc
46 | @ContextConfiguration(classes = {OrderServiceConfig.class})
47 | public class OrderControllerTest {
48 |
49 | @Autowired
50 | private OrderService orderService;
51 |
52 | @Autowired
53 | private OrderRepository orderRepository;
54 |
55 | @Autowired
56 | private MockMvc mockMvc;
57 |
58 | @Autowired
59 | private CircuitBreakerRegistry circuitBreakerRegistry;
60 |
61 | @RegisterExtension
62 | static WireMockExtension wireMockServer
63 | = WireMockExtension.newInstance()
64 | .options(WireMockConfiguration
65 | .wireMockConfig()
66 | .port(8088))
67 | .build();
68 |
69 | private ObjectMapper objectMapper
70 | = new ObjectMapper()
71 | .findAndRegisterModules()
72 | .configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false)
73 | .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
74 |
75 |
76 | @BeforeEach
77 | void setup() throws IOException {
78 | getProductDetailsResponse();
79 | doPayment();
80 | getPaymentDetails();
81 | reduceQuantity();
82 | }
83 |
84 | private void reduceQuantity() {
85 | circuitBreakerRegistry.circuitBreaker("external").reset();
86 | wireMockServer.stubFor(put(urlMatching("/product/reduceQuantity/.*"))
87 | .willReturn(aResponse()
88 | .withStatus(HttpStatus.OK.value())
89 | .withHeader("Content-Type", MediaType.APPLICATION_JSON_VALUE)));
90 | }
91 |
92 | private void getPaymentDetails() throws IOException {
93 | circuitBreakerRegistry.circuitBreaker("external").reset();
94 | wireMockServer.stubFor(get(urlMatching("/payment/.*"))
95 | .willReturn(aResponse()
96 | .withStatus(HttpStatus.OK.value())
97 | .withHeader("Content-Type", MediaType.APPLICATION_JSON_VALUE)
98 | .withBody(
99 | copyToString(
100 | OrderControllerTest.class
101 | .getClassLoader()
102 | .getResourceAsStream("mock/GetPayment.json"),
103 | defaultCharset()
104 | )
105 | )));
106 | }
107 |
108 | private void doPayment() {
109 | wireMockServer.stubFor(post(urlEqualTo("/payment"))
110 | .willReturn(aResponse()
111 | .withStatus(HttpStatus.OK.value())
112 | .withHeader("Content-Type", MediaType.APPLICATION_JSON_VALUE)));
113 | }
114 |
115 | private void getProductDetailsResponse() throws IOException {
116 | // GET /product/1
117 | wireMockServer.stubFor(get("/product/1")
118 | .willReturn(aResponse()
119 | .withStatus(HttpStatus.OK.value())
120 | .withHeader("Content-Type", MediaType.APPLICATION_JSON_VALUE)
121 | .withBody(copyToString(
122 | OrderControllerTest.class
123 | .getClassLoader()
124 | .getResourceAsStream("mock/GetProduct.json"),
125 | defaultCharset()
126 | ))));
127 |
128 |
129 | }
130 |
131 |
132 | private OrderRequest getMockOrderRequest() {
133 | return OrderRequest.builder()
134 | .productId(1)
135 | .paymentMode(PaymentMode.CASH)
136 | .quantity(10)
137 | .totalAmount(200)
138 | .build();
139 | }
140 |
141 | @Test
142 | public void test_WhenPlaceOrder_DoPayment_Success() throws Exception {
143 | //First Place Order
144 | // Get Order by Order Id from Db and check
145 | //Check Output
146 |
147 | OrderRequest orderRequest = getMockOrderRequest();
148 | MvcResult mvcResult
149 | = mockMvc.perform(MockMvcRequestBuilders.post("/order/placeOrder")
150 | .with(jwt().authorities(new SimpleGrantedAuthority("Customer")))
151 | .contentType(MediaType.APPLICATION_JSON_VALUE)
152 | .content(objectMapper.writeValueAsString(orderRequest))
153 | ).andExpect(MockMvcResultMatchers.status().isOk())
154 | .andReturn();
155 |
156 | String orderId = mvcResult.getResponse().getContentAsString();
157 |
158 | Optional order = orderRepository.findById(Long.valueOf(orderId));
159 | assertTrue(order.isPresent());
160 |
161 | Order o = order.get();
162 |
163 | assertEquals(Long.parseLong(orderId), o.getId());
164 | assertEquals("PLACED", o.getOrderStatus());
165 | assertEquals(orderRequest.getTotalAmount(), o.getAmount());
166 | assertEquals(orderRequest.getQuantity(), o.getQuantity());
167 |
168 | }
169 |
170 | @Test
171 | public void test_WhenPlaceOrderWithWrongAccess_thenThrow403() throws Exception {
172 | OrderRequest orderRequest = getMockOrderRequest();
173 | MvcResult mvcResult
174 | = mockMvc.perform(MockMvcRequestBuilders.post("/order/placeOrder")
175 | .with(jwt().authorities(new SimpleGrantedAuthority("Admin")))
176 | .contentType(MediaType.APPLICATION_JSON_VALUE)
177 | .content(objectMapper.writeValueAsString(orderRequest))
178 | ).andExpect(MockMvcResultMatchers.status().isForbidden())
179 | .andReturn();
180 | }
181 |
182 |
183 | /*@Test
184 | public void test_WhenGetOrder_Success() throws Exception {
185 | MvcResult mvcResult
186 | = mockMvc.perform(MockMvcRequestBuilders.get("/order/1")
187 | .with(jwt().authorities(new SimpleGrantedAuthority("Admin")))
188 | .contentType(MediaType.APPLICATION_JSON_VALUE))
189 | .andExpect(MockMvcResultMatchers.status().isOk())
190 | .andReturn();
191 |
192 | String actualResponse = mvcResult.getResponse().getContentAsString();
193 | Order order = orderRepository.findById(1L).get();
194 | String expectedResponse = getOrderResponse(order);
195 |
196 |
197 | assertEquals(expectedResponse, actualResponse);
198 | }*/
199 |
200 | @Test
201 | public void testWhen_GetOrder_Order_Not_Found() throws Exception {
202 | MvcResult mvcResult
203 | = mockMvc.perform(MockMvcRequestBuilders.get("/order/100")
204 | .with(jwt().authorities(new SimpleGrantedAuthority("Admin")))
205 | .contentType(MediaType.APPLICATION_JSON_VALUE))
206 | .andExpect(MockMvcResultMatchers.status().isNotFound())
207 | .andReturn();
208 | }
209 |
210 | private String getOrderResponse(Order order) throws IOException {
211 | OrderResponse.PaymentDetails paymentDetails
212 | = objectMapper.readValue(
213 | copyToString(
214 | OrderControllerTest.class.getClassLoader()
215 | .getResourceAsStream("mock/GetPayment.json"
216 | ),
217 | defaultCharset()
218 | ), OrderResponse.PaymentDetails.class
219 | );
220 | paymentDetails.setPaymentStatus("SUCCESS");
221 |
222 | OrderResponse.ProductDetails productDetails
223 | = objectMapper.readValue(
224 | copyToString(
225 | OrderControllerTest.class.getClassLoader()
226 | .getResourceAsStream("mock/GetProduct.json"),
227 | defaultCharset()
228 | ), OrderResponse.ProductDetails.class
229 | );
230 |
231 | OrderResponse orderResponse
232 | = OrderResponse.builder()
233 | .paymentDetails(paymentDetails)
234 | .productDetails(productDetails)
235 | .orderStatus(order.getOrderStatus())
236 | .orderDate(order.getOrderDate())
237 | .amount(order.getAmount())
238 | .orderId(order.getId())
239 | .build();
240 | return objectMapper.writeValueAsString(orderResponse);
241 | }
242 |
243 | }
244 |
--------------------------------------------------------------------------------
/OrderService/src/test/java/com/msbeigi/orderservice/services/OrderServiceImplTest.java:
--------------------------------------------------------------------------------
1 | package com.msbeigi.orderservice.services;
2 |
3 | import com.msbeigi.orderservice.entity.Order;
4 | import com.msbeigi.orderservice.exception.CustomException;
5 | import com.msbeigi.orderservice.external.client.PaymentService;
6 | import com.msbeigi.orderservice.external.client.ProductService;
7 | import com.msbeigi.orderservice.external.request.PaymentRequest;
8 | import com.msbeigi.orderservice.external.response.PaymentResponse;
9 | import com.msbeigi.orderservice.external.response.ProductResponse;
10 | import com.msbeigi.orderservice.model.OrderRequest;
11 | import com.msbeigi.orderservice.model.OrderResponse;
12 | import com.msbeigi.orderservice.model.PaymentMode;
13 | import com.msbeigi.orderservice.repository.OrderRepository;
14 | import org.junit.jupiter.api.Assertions;
15 | import org.junit.jupiter.api.DisplayName;
16 | import org.junit.jupiter.api.Test;
17 | import org.mockito.ArgumentMatchers;
18 | import org.mockito.InjectMocks;
19 | import org.mockito.Mock;
20 | import org.mockito.Mockito;
21 | import org.springframework.beans.factory.annotation.Autowired;
22 | import org.springframework.boot.test.context.SpringBootTest;
23 | import org.springframework.http.HttpStatus;
24 | import org.springframework.http.ResponseEntity;
25 | import org.springframework.web.client.RestTemplate;
26 |
27 | import java.time.Instant;
28 | import java.util.Optional;
29 |
30 | import static org.junit.jupiter.api.Assertions.*;
31 | import static org.mockito.ArgumentMatchers.*;
32 | import static org.mockito.Mockito.*;
33 |
34 | @SpringBootTest
35 | public class OrderServiceImplTest {
36 |
37 | @Mock
38 | private OrderRepository orderRepository;
39 |
40 | @Mock
41 | private ProductService productService;
42 |
43 | @Mock
44 | private PaymentService paymentService;
45 |
46 | @Mock
47 | private RestTemplate restTemplate;
48 |
49 | @InjectMocks
50 | OrderService orderService = new OrderServiceImpl();
51 |
52 |
53 | @DisplayName("Get Order - Success Scenario")
54 | @Test
55 | void test_When_Order_Success() {
56 | //Mocking
57 | Order order = getMockOrder();
58 | when(orderRepository.findById(anyLong()))
59 | .thenReturn(Optional.of(order));
60 |
61 | when(restTemplate.getForObject(
62 | "http://PRODUCT-SERVICE/product/" + order.getProductId(),
63 | ProductResponse.class
64 | )).thenReturn(getMockProductResponse());
65 |
66 | when(restTemplate.getForObject(
67 | "http://PAYMENT-SERVICE/payment/order/" + order.getId(),
68 | PaymentResponse.class
69 | )).thenReturn(getMockPaymentResponse());
70 |
71 | //Actual
72 | OrderResponse orderResponse = orderService.getOrderDetailsById(1);
73 |
74 | //Verification
75 | verify(orderRepository, times(1)).findById(anyLong());
76 | verify(restTemplate, times(1)).getForObject(
77 | "http://PRODUCT-SERVICE/product/" + order.getProductId(),
78 | ProductResponse.class);
79 | verify(restTemplate, times(1)).getForObject(
80 | "http://PAYMENT-SERVICE/payment/order/" + order.getId(),
81 | PaymentResponse.class);
82 |
83 |
84 | //Assert
85 | assertNotNull(orderResponse);
86 | assertEquals(order.getId(), orderResponse.getOrderId());
87 | }
88 |
89 | @DisplayName("Get Orders - Failure Scenario")
90 | @Test
91 | void test_When_Get_Order_NOT_FOUND_then_Not_Found() {
92 |
93 | when(orderRepository.findById(anyLong()))
94 | .thenReturn(Optional.ofNullable(null));
95 |
96 | CustomException exception =
97 | assertThrows(CustomException.class,
98 | () -> orderService.getOrderDetailsById(1));
99 | assertEquals("NOT_FOUND", exception.getErrorCode());
100 | assertEquals(404, exception.getStatus());
101 |
102 | verify(orderRepository, times(1))
103 | .findById(anyLong());
104 | }
105 |
106 | @DisplayName("Place Order - Success Scenario")
107 | @Test
108 | void test_When_Place_Order_Success() {
109 | Order order = getMockOrder();
110 | OrderRequest orderRequest = getMockOrderRequest();
111 |
112 | when(orderRepository.save(any(Order.class)))
113 | .thenReturn(order);
114 | when(productService.reduceQuantity(anyLong(),anyLong()))
115 | .thenReturn(new ResponseEntity(HttpStatus.OK));
116 | when(paymentService.doPayment(any(PaymentRequest.class)))
117 | .thenReturn(new ResponseEntity(1L,HttpStatus.OK));
118 |
119 | long orderId = orderService.placeOrder(orderRequest);
120 |
121 | verify(orderRepository, times(2))
122 | .save(any());
123 | verify(productService, times(1))
124 | .reduceQuantity(anyLong(),anyLong());
125 | verify(paymentService, times(1))
126 | .doPayment(any(PaymentRequest.class));
127 |
128 | assertEquals(order.getId(), orderId);
129 | }
130 |
131 | @DisplayName("Place Order - Payment Failed Scenario")
132 | @Test
133 | void test_when_Place_Order_Payment_Fails_then_Order_Placed() {
134 |
135 | Order order = getMockOrder();
136 | OrderRequest orderRequest = getMockOrderRequest();
137 |
138 | when(orderRepository.save(any(Order.class)))
139 | .thenReturn(order);
140 | when(productService.reduceQuantity(anyLong(),anyLong()))
141 | .thenReturn(new ResponseEntity(HttpStatus.OK));
142 | when(paymentService.doPayment(any(PaymentRequest.class)))
143 | .thenThrow(new RuntimeException());
144 |
145 | long orderId = orderService.placeOrder(orderRequest);
146 |
147 | verify(orderRepository, times(2))
148 | .save(any());
149 | verify(productService, times(1))
150 | .reduceQuantity(anyLong(),anyLong());
151 | verify(paymentService, times(1))
152 | .doPayment(any(PaymentRequest.class));
153 |
154 | assertEquals(order.getId(), orderId);
155 | }
156 |
157 | private OrderRequest getMockOrderRequest() {
158 | return OrderRequest.builder()
159 | .productId(1)
160 | .quantity(10)
161 | .paymentMode(PaymentMode.CASH)
162 | .totalAmount(100)
163 | .build();
164 | }
165 |
166 | private PaymentResponse getMockPaymentResponse() {
167 | return PaymentResponse.builder()
168 | .paymentId(1)
169 | .paymentDate(Instant.now())
170 | .paymentMode(PaymentMode.CASH)
171 | .amount(200)
172 | .orderId(1)
173 | .status("ACCEPTED")
174 | .build();
175 | }
176 |
177 | private ProductResponse getMockProductResponse() {
178 | return ProductResponse.builder()
179 | .productId(2)
180 | .productName("iPhone")
181 | .price(100)
182 | .quantity(200)
183 | .build();
184 | }
185 |
186 | private Order getMockOrder() {
187 | return Order.builder()
188 | .orderStatus("PLACED")
189 | .orderDate(Instant.now())
190 | .id(1)
191 | .amount(100)
192 | .quantity(200)
193 | .productId(2)
194 | .build();
195 | }
196 |
197 | }
198 |
--------------------------------------------------------------------------------
/OrderService/src/test/resources/application.yaml:
--------------------------------------------------------------------------------
1 | spring:
2 | datasource:
3 | url: jdbc:h2:mem:order
4 | username: sa
5 | password: password
6 | driverClassName: org.h2.Driver
7 | jpa:
8 | database-platform: org.hibernate.dialect.H2Dialect
9 | config:
10 | import: optional:configserver:http://localhost:9296
11 | security:
12 | oauth2:
13 | resourceserver:
14 | jwt:
15 | issuer-uri: https://dev-64973606.okta.com/oauth2/default
16 | client:
17 | registration:
18 | internal-client:
19 | provider: okta
20 | authorization-grant-type: client_credentials
21 | scope: internal
22 | client-id: 0oaa4cqbuyzWeNFec5d7
23 | client-secret: 1TQczKd2HajEL74KggFBLI5uKHDexYU5-ybSYKms
24 | provider:
25 | okta:
26 | issuer-uri: https://dev-64973606.okta.com/oauth2/default
27 |
28 | eureka:
29 | client:
30 | enabled: false
31 |
--------------------------------------------------------------------------------
/OrderService/src/test/resources/mock/GetPayment.json:
--------------------------------------------------------------------------------
1 | {
2 | "paymentId": 1,
3 | "paymentMode": "CASH",
4 | "status": "SUCCESS",
5 | "amount": 500,
6 | "paymentDate": "2022-03-20T10:06:10.060802Z",
7 | "orderId": 1
8 | }
9 |
--------------------------------------------------------------------------------
/OrderService/src/test/resources/mock/GetProduct.json:
--------------------------------------------------------------------------------
1 | {
2 | "productId": 1,
3 | "productName": "iPhone",
4 | "quantity": 370,
5 | "price": 200
6 | }
7 |
--------------------------------------------------------------------------------
/PaymentService/.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 |
--------------------------------------------------------------------------------
/PaymentService/.mvn/wrapper/maven-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/msbeigiai/spring-boot-microservices/7c41c629c582ed45a45722b1ec1dba5fbe4574b3/PaymentService/.mvn/wrapper/maven-wrapper.jar
--------------------------------------------------------------------------------
/PaymentService/.mvn/wrapper/maven-wrapper.properties:
--------------------------------------------------------------------------------
1 | # Licensed to the Apache Software Foundation (ASF) under one
2 | # or more contributor license agreements. See the NOTICE file
3 | # distributed with this work for additional information
4 | # regarding copyright ownership. The ASF licenses this file
5 | # to you under the Apache License, Version 2.0 (the
6 | # "License"); you may not use this file except in compliance
7 | # with the License. You may obtain a copy of the License at
8 | #
9 | # https://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.7/apache-maven-3.8.7-bin.zip
18 | wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.1/maven-wrapper-3.1.1.jar
19 |
--------------------------------------------------------------------------------
/PaymentService/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM openjdk:17
2 |
3 | ARG JAR_FILE=target/*.jar
4 |
5 | COPY ${JAR_FILE} paymentservice.jar
6 |
7 | ENTRYPOINT ["java", "-jar", "/paymentservice.jar"]
8 |
9 | EXPOSE 8082
10 |
11 |
--------------------------------------------------------------------------------
/PaymentService/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 |
--------------------------------------------------------------------------------
/PaymentService/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | org.springframework.boot
7 | spring-boot-starter-parent
8 | 2.7.13
9 |
10 |
11 | com.msbeigi
12 | PaymentService
13 | 0.0.1
14 | PaymentService
15 | Demo project for Spring Boot
16 |
17 | 17
18 | 2021.0.7
19 |
20 |
21 |
22 | org.springframework.boot
23 | spring-boot-starter-data-jpa
24 |
25 |
26 | org.springframework.boot
27 | spring-boot-starter-web
28 |
29 |
30 | org.springframework.cloud
31 | spring-cloud-sleuth-zipkin
32 |
33 |
34 | org.springframework.cloud
35 | spring-cloud-starter-sleuth
36 |
37 |
38 | org.springframework.cloud
39 | spring-cloud-starter
40 |
41 |
42 | org.springframework.cloud
43 | spring-cloud-starter-config
44 |
45 |
46 | org.springframework.cloud
47 | spring-cloud-starter-netflix-eureka-client
48 |
49 |
50 | org.springframework.boot
51 | spring-boot-starter-security
52 |
53 |
54 | com.okta.spring
55 | okta-spring-boot-starter
56 | 2.1.6
57 |
58 |
59 |
60 | com.mysql
61 | mysql-connector-j
62 | runtime
63 |
64 |
65 | org.projectlombok
66 | lombok
67 | true
68 |
69 |
70 | org.springframework.boot
71 | spring-boot-starter-test
72 | test
73 |
74 |
75 |
76 |
77 |
78 | org.springframework.cloud
79 | spring-cloud-dependencies
80 | ${spring-cloud.version}
81 | pom
82 | import
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 | org.springframework.boot
91 | spring-boot-maven-plugin
92 |
93 |
94 |
95 | org.projectlombok
96 | lombok
97 |
98 |
99 |
100 |
101 |
102 | com.google.cloud.tools
103 | jib-maven-plugin
104 |
105 |
106 | openjdk:17
107 |
108 |
109 | registry.hub.docker.com/msbeigiai/paymentservice
110 | ${project.version}
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
--------------------------------------------------------------------------------
/PaymentService/src/main/java/com/msbeigi/paymentservice/PaymentServiceApplication.java:
--------------------------------------------------------------------------------
1 | package com.msbeigi.paymentservice;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 |
6 | @SpringBootApplication
7 | public class PaymentServiceApplication {
8 |
9 | public static void main(String[] args) {
10 | SpringApplication.run(PaymentServiceApplication.class, args);
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/PaymentService/src/main/java/com/msbeigi/paymentservice/controller/PaymentController.java:
--------------------------------------------------------------------------------
1 | package com.msbeigi.paymentservice.controller;
2 |
3 | import com.msbeigi.paymentservice.model.PaymentRequest;
4 | import com.msbeigi.paymentservice.model.PaymentResponse;
5 | import com.msbeigi.paymentservice.services.PaymentService;
6 | import org.springframework.beans.factory.annotation.Autowired;
7 | import org.springframework.http.HttpStatus;
8 | import org.springframework.http.ResponseEntity;
9 | import org.springframework.web.bind.annotation.*;
10 |
11 | @RestController
12 | @RequestMapping("/payment")
13 | public class PaymentController {
14 |
15 | @Autowired
16 | private PaymentService paymentService;
17 |
18 | @PostMapping
19 | public ResponseEntity doPayment(@RequestBody PaymentRequest paymentRequest) {
20 | return new ResponseEntity<>(
21 | paymentService.doPayment(paymentRequest),
22 | HttpStatus.CREATED
23 | );
24 | }
25 |
26 | @GetMapping("/order/{orderId}")
27 | public ResponseEntity getPaymentDetailsByOrderId(@PathVariable String orderId) {
28 | return new ResponseEntity<>(
29 | paymentService.getPaymentDetailsByOrderId(orderId),
30 | HttpStatus.OK
31 | );
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/PaymentService/src/main/java/com/msbeigi/paymentservice/entity/TransactionDetails.java:
--------------------------------------------------------------------------------
1 | package com.msbeigi.paymentservice.entity;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Builder;
5 | import lombok.Data;
6 | import lombok.NoArgsConstructor;
7 |
8 | import javax.persistence.*;
9 | import java.time.Instant;
10 |
11 | @Entity
12 | @Table(name = "transaction_details")
13 | @Data
14 | @AllArgsConstructor
15 | @NoArgsConstructor
16 | @Builder
17 | public class TransactionDetails {
18 |
19 | @Id
20 | @GeneratedValue(strategy = GenerationType.AUTO)
21 | private long id;
22 |
23 | @Column(name = "order_id")
24 | private long orderId;
25 |
26 | @Column(name = "mode")
27 | private String paymentMode;
28 |
29 | @Column(name = "reference_number")
30 | private String referenceNumber;
31 |
32 | @Column(name = "payment_date")
33 | private Instant paymentDate;
34 |
35 | @Column(name = "status")
36 | private String paymentStatus;
37 |
38 | @Column(name = "amount")
39 | private long amount;
40 | }
41 |
--------------------------------------------------------------------------------
/PaymentService/src/main/java/com/msbeigi/paymentservice/model/PaymentMode.java:
--------------------------------------------------------------------------------
1 | package com.msbeigi.paymentservice.model;
2 |
3 | public enum PaymentMode {
4 | CASH,
5 | PAYPAL,
6 | DEBIT_CARD,
7 | CREDIT_CARD,
8 | APPLE_PAY
9 | }
10 |
--------------------------------------------------------------------------------
/PaymentService/src/main/java/com/msbeigi/paymentservice/model/PaymentRequest.java:
--------------------------------------------------------------------------------
1 | package com.msbeigi.paymentservice.model;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Builder;
5 | import lombok.Data;
6 | import lombok.NoArgsConstructor;
7 |
8 | @Data
9 | @NoArgsConstructor
10 | @AllArgsConstructor
11 | @Builder
12 | public class PaymentRequest {
13 |
14 | private long orderId;
15 | private long amount;
16 | private String referenceNumber;
17 | private PaymentMode paymentMode;
18 | }
19 |
--------------------------------------------------------------------------------
/PaymentService/src/main/java/com/msbeigi/paymentservice/model/PaymentResponse.java:
--------------------------------------------------------------------------------
1 | package com.msbeigi.paymentservice.model;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Builder;
5 | import lombok.Data;
6 | import lombok.NoArgsConstructor;
7 |
8 | import java.time.Instant;
9 |
10 | @Data
11 | @AllArgsConstructor
12 | @NoArgsConstructor
13 | @Builder
14 | public class PaymentResponse {
15 | private long paymentId;
16 | private String status;
17 | private PaymentMode paymentMode;
18 | private long amount;
19 | private Instant paymentDate;
20 | private long orderId;
21 | }
22 |
--------------------------------------------------------------------------------
/PaymentService/src/main/java/com/msbeigi/paymentservice/repository/TransactionsDetailsRepository.java:
--------------------------------------------------------------------------------
1 | package com.msbeigi.paymentservice.repository;
2 |
3 | import com.msbeigi.paymentservice.entity.TransactionDetails;
4 | import org.springframework.data.jpa.repository.JpaRepository;
5 | import org.springframework.stereotype.Repository;
6 |
7 | @Repository
8 | public interface TransactionsDetailsRepository extends JpaRepository {
9 |
10 | TransactionDetails findByOrderId(long orderId);
11 | }
12 |
--------------------------------------------------------------------------------
/PaymentService/src/main/java/com/msbeigi/paymentservice/security/WebSecurityConfig.java:
--------------------------------------------------------------------------------
1 | package com.msbeigi.paymentservice.security;
2 |
3 | import org.springframework.context.annotation.Bean;
4 | import org.springframework.context.annotation.Configuration;
5 | import org.springframework.security.config.annotation.web.builders.HttpSecurity;
6 | import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
7 | import org.springframework.security.config.annotation.web.configurers.oauth2.server.resource.OAuth2ResourceServerConfigurer;
8 | import org.springframework.security.web.SecurityFilterChain;
9 |
10 | @Configuration
11 | @EnableWebSecurity
12 | public class WebSecurityConfig {
13 |
14 | @Bean
15 | SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
16 | http.authorizeHttpRequests(authorizedRequest ->
17 | authorizedRequest
18 | .antMatchers("/payment/**")
19 | .hasAuthority("SCOPE_internal")
20 | .anyRequest()
21 | .authenticated()
22 | )
23 | .oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt);
24 |
25 | return http.build();
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/PaymentService/src/main/java/com/msbeigi/paymentservice/services/PaymentService.java:
--------------------------------------------------------------------------------
1 | package com.msbeigi.paymentservice.services;
2 |
3 | import com.msbeigi.paymentservice.model.PaymentRequest;
4 | import com.msbeigi.paymentservice.model.PaymentResponse;
5 | import org.springframework.stereotype.Service;
6 |
7 | public interface PaymentService {
8 | long doPayment(PaymentRequest paymentRequest);
9 |
10 | PaymentResponse getPaymentDetailsByOrderId(String orderId);
11 | }
12 |
--------------------------------------------------------------------------------
/PaymentService/src/main/java/com/msbeigi/paymentservice/services/PaymentServiceImpl.java:
--------------------------------------------------------------------------------
1 | package com.msbeigi.paymentservice.services;
2 |
3 | import com.msbeigi.paymentservice.entity.TransactionDetails;
4 | import com.msbeigi.paymentservice.model.PaymentMode;
5 | import com.msbeigi.paymentservice.model.PaymentRequest;
6 | import com.msbeigi.paymentservice.model.PaymentResponse;
7 | import com.msbeigi.paymentservice.repository.TransactionsDetailsRepository;
8 | import lombok.extern.log4j.Log4j2;
9 | import org.springframework.beans.factory.annotation.Autowired;
10 | import org.springframework.stereotype.Service;
11 |
12 | import java.time.Instant;
13 |
14 | @Service
15 | @Log4j2
16 | public class PaymentServiceImpl implements PaymentService {
17 |
18 | @Autowired
19 | private TransactionsDetailsRepository transactionsDetailsRepository;
20 |
21 | @Override
22 | public long doPayment(PaymentRequest paymentRequest) {
23 | log.info("Recording Payment Details: {}", paymentRequest);
24 |
25 | TransactionDetails transactionDetails =
26 | TransactionDetails.builder()
27 | .referenceNumber(paymentRequest.getReferenceNumber())
28 | .paymentDate(Instant.now())
29 | .paymentMode(paymentRequest.getPaymentMode().name())
30 | .amount(paymentRequest.getAmount())
31 | .orderId(paymentRequest.getOrderId())
32 | .paymentStatus("SUCCESS")
33 | .build();
34 | transactionsDetailsRepository.save(transactionDetails);
35 |
36 | log.info("Transaction completed with Id: {}", transactionDetails.getId());
37 | return transactionDetails.getId();
38 | }
39 |
40 | @Override
41 | public PaymentResponse getPaymentDetailsByOrderId(String orderId) {
42 | log.info("Getting payment details for the order id: {}", orderId);
43 |
44 | TransactionDetails transactionDetails =
45 | transactionsDetailsRepository.findByOrderId(Long.parseLong(orderId));
46 |
47 | return PaymentResponse
48 | .builder()
49 | .paymentId(transactionDetails.getId())
50 | .paymentMode(PaymentMode.valueOf(transactionDetails.getPaymentMode()))
51 | .paymentDate(transactionDetails.getPaymentDate())
52 | .orderId(transactionDetails.getOrderId())
53 | .status(transactionDetails.getPaymentStatus())
54 | .amount(transactionDetails.getAmount())
55 | .build();
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/PaymentService/src/main/resources/application.yaml:
--------------------------------------------------------------------------------
1 | server:
2 | port: 8081
3 |
4 | spring:
5 | datasource:
6 | url: jdbc:mysql://${DB_HOST:localhost}:3306/payment_db
7 | username: root
8 | password: root
9 | driver-class-name: com.mysql.cj.jdbc.Driver
10 | jpa:
11 | database-platform: org.hibernate.dialect.MySQL57InnoDBDialect
12 | hibernate:
13 | ddl-auto: update
14 |
15 | application:
16 | name: PAYMENT-SERVICE
17 |
18 | config:
19 | import: configserver:${CONFIG_SERVER_URL:http://localhost:9296}
20 |
21 |
--------------------------------------------------------------------------------
/PaymentService/src/test/java/com/msbeigi/paymentservice/PaymentServiceApplicationTests.java:
--------------------------------------------------------------------------------
1 | package com.msbeigi.paymentservice;
2 |
3 | import org.junit.jupiter.api.Test;
4 | import org.springframework.boot.test.context.SpringBootTest;
5 |
6 | @SpringBootTest
7 | class PaymentServiceApplicationTests {
8 |
9 | @Test
10 | void contextLoads() {
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/ProductService/.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 |
--------------------------------------------------------------------------------
/ProductService/.mvn/wrapper/maven-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/msbeigiai/spring-boot-microservices/7c41c629c582ed45a45722b1ec1dba5fbe4574b3/ProductService/.mvn/wrapper/maven-wrapper.jar
--------------------------------------------------------------------------------
/ProductService/.mvn/wrapper/maven-wrapper.properties:
--------------------------------------------------------------------------------
1 | # Licensed to the Apache Software Foundation (ASF) under one
2 | # or more contributor license agreements. See the NOTICE file
3 | # distributed with this work for additional information
4 | # regarding copyright ownership. The ASF licenses this file
5 | # to you under the Apache License, Version 2.0 (the
6 | # "License"); you may not use this file except in compliance
7 | # with the License. You may obtain a copy of the License at
8 | #
9 | # https://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.7/apache-maven-3.8.7-bin.zip
18 | wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.1/maven-wrapper-3.1.1.jar
19 |
--------------------------------------------------------------------------------
/ProductService/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM openjdk:17
2 |
3 | ARG JAR_FILE=target/*.jar
4 |
5 | COPY ${JAR_FILE} productservice.jar
6 |
7 | ENTRYPOINT ["java", "-jar", "/productservice.jar"]
8 |
9 | EXPOSE 8082
10 |
11 |
--------------------------------------------------------------------------------
/ProductService/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 |
--------------------------------------------------------------------------------
/ProductService/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | org.springframework.boot
7 | spring-boot-starter-parent
8 | 2.7.12
9 |
10 |
11 | com.msbeigi
12 | ProductService
13 | 0.0.1
14 | ProductService
15 | Demo project for Spring Boot
16 |
17 | 17
18 | 2021.0.7
19 |
20 |
21 |
22 | org.springframework.boot
23 | spring-boot-starter-data-jpa
24 |
25 |
26 | org.springframework.boot
27 | spring-boot-starter-web
28 |
29 |
30 | org.springframework.cloud
31 | spring-cloud-starter
32 |
33 |
34 |
35 | com.mysql
36 | mysql-connector-j
37 | runtime
38 |
39 |
40 | org.projectlombok
41 | lombok
42 | true
43 |
44 |
45 | org.springframework.boot
46 | spring-boot-starter-test
47 | test
48 |
49 |
50 |
51 | org.springframework.cloud
52 | spring-cloud-starter-netflix-eureka-client
53 |
54 |
55 |
56 | org.springframework.cloud
57 | spring-cloud-starter-config
58 |
59 |
60 |
61 | org.springframework.cloud
62 | spring-cloud-sleuth-zipkin
63 |
64 |
65 | org.springframework.cloud
66 | spring-cloud-starter-sleuth
67 |
68 |
69 | org.springframework.boot
70 | spring-boot-starter-security
71 |
72 |
73 | com.okta.spring
74 | okta-spring-boot-starter
75 | 2.1.6
76 |
77 |
78 |
79 |
80 |
81 | org.springframework.cloud
82 | spring-cloud-dependencies
83 | ${spring-cloud.version}
84 | pom
85 | import
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 | org.springframework.boot
94 | spring-boot-maven-plugin
95 |
96 |
97 |
98 | org.projectlombok
99 | lombok
100 |
101 |
102 |
103 |
104 |
105 | com.google.cloud.tools
106 | jib-maven-plugin
107 |
108 |
109 | openjdk:17
110 |
111 |
112 | registry.hub.docker.com/msbeigiai/productservice
113 | ${project.version}
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
--------------------------------------------------------------------------------
/ProductService/src/main/java/com/msbeigi/ProductService/ProductServiceApplication.java:
--------------------------------------------------------------------------------
1 | package com.msbeigi.ProductService;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 |
6 | @SpringBootApplication
7 | public class ProductServiceApplication {
8 |
9 | public static void main(String[] args) {
10 | SpringApplication.run(ProductServiceApplication.class, args);
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/ProductService/src/main/java/com/msbeigi/ProductService/controller/ProductController.java:
--------------------------------------------------------------------------------
1 | package com.msbeigi.ProductService.controller;
2 |
3 | import com.msbeigi.ProductService.model.ProductRequest;
4 | import com.msbeigi.ProductService.model.ProductResponse;
5 | import com.msbeigi.ProductService.services.ProductService;
6 | import org.springframework.beans.factory.annotation.Autowired;
7 | import org.springframework.http.HttpStatus;
8 | import org.springframework.http.ResponseEntity;
9 | import org.springframework.security.access.prepost.PreAuthorize;
10 | import org.springframework.web.bind.annotation.*;
11 |
12 | @RestController
13 | @RequestMapping("/product")
14 | public class ProductController {
15 |
16 | @Autowired
17 | private ProductService productService;
18 |
19 | @PreAuthorize("hasAuthority('Admin')")
20 | @PostMapping
21 | public ResponseEntity addProduct(@RequestBody ProductRequest productRequest) {
22 | long productId = productService.addProduct(productRequest);
23 | return new ResponseEntity<>(productId, HttpStatus.CREATED);
24 | }
25 |
26 | @PreAuthorize("hasAuthority('Admin') || hasAuthority('Customer') || hasAuthority('SCOPE_internal')")
27 | @GetMapping("/{id}")
28 | public ResponseEntity getProductById(@PathVariable("id") long productId) {
29 | ProductResponse productResponse =
30 | productService.getProductById(productId);
31 | return new ResponseEntity<>(productResponse, HttpStatus.OK);
32 | }
33 |
34 | @PutMapping("/reduceQuantity/{id}")
35 | public ResponseEntity reduceQuantity(
36 | @PathVariable("id") long productId,
37 | @RequestParam long quantity) {
38 | productService.reduceQuantity(productId, quantity);
39 | return new ResponseEntity<>(HttpStatus.OK);
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/ProductService/src/main/java/com/msbeigi/ProductService/entity/Product.java:
--------------------------------------------------------------------------------
1 | package com.msbeigi.ProductService.entity;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Builder;
5 | import lombok.Data;
6 | import lombok.NoArgsConstructor;
7 |
8 | import javax.persistence.*;
9 |
10 | @Data
11 | @AllArgsConstructor
12 | @NoArgsConstructor
13 | @Builder
14 | @Entity
15 | @Table(name = "product")
16 | public class Product {
17 |
18 | @Id
19 | @GeneratedValue(strategy = GenerationType.AUTO)
20 | private long productId;
21 |
22 | @Column(name = "product_name")
23 | private String productName;
24 |
25 | @Column(name = "price")
26 | private long price;
27 |
28 | @Column(name = "quantity")
29 | private long quantity;
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/ProductService/src/main/java/com/msbeigi/ProductService/exception/ProductServiceCustomException.java:
--------------------------------------------------------------------------------
1 | package com.msbeigi.ProductService.exception;
2 |
3 | import lombok.Data;
4 |
5 | @Data
6 | public class ProductServiceCustomException extends RuntimeException {
7 | private String errorCode;
8 |
9 | public ProductServiceCustomException(String message, String errorCode) {
10 | super(message);
11 | this.errorCode = errorCode;
12 | }
13 |
14 | }
15 |
--------------------------------------------------------------------------------
/ProductService/src/main/java/com/msbeigi/ProductService/exception/RestResponseEntityExceptionHandler.java:
--------------------------------------------------------------------------------
1 | package com.msbeigi.ProductService.exception;
2 |
3 | import com.msbeigi.ProductService.model.ErrorResponse;
4 | import org.springframework.http.HttpStatus;
5 | import org.springframework.http.ResponseEntity;
6 | import org.springframework.web.bind.annotation.ControllerAdvice;
7 | import org.springframework.web.bind.annotation.ExceptionHandler;
8 | import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
9 |
10 | @ControllerAdvice
11 | public class RestResponseEntityExceptionHandler extends ResponseEntityExceptionHandler {
12 |
13 | @ExceptionHandler(ProductServiceCustomException.class)
14 | public ResponseEntity handleProductServiceException(ProductServiceCustomException exception) {
15 | return new ResponseEntity<>(ErrorResponse.builder()
16 | .errorMessage(exception.getMessage())
17 | .errorCode(exception.getErrorCode())
18 | .build(),
19 | HttpStatus.NOT_FOUND);
20 | }
21 |
22 | }
23 |
--------------------------------------------------------------------------------
/ProductService/src/main/java/com/msbeigi/ProductService/model/ErrorResponse.java:
--------------------------------------------------------------------------------
1 | package com.msbeigi.ProductService.model;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Builder;
5 | import lombok.Data;
6 | import lombok.NoArgsConstructor;
7 |
8 | @Data
9 | @AllArgsConstructor
10 | @NoArgsConstructor
11 | @Builder
12 | public class ErrorResponse {
13 |
14 | private String errorMessage;
15 | private String errorCode;
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/ProductService/src/main/java/com/msbeigi/ProductService/model/ProductRequest.java:
--------------------------------------------------------------------------------
1 | package com.msbeigi.ProductService.model;
2 |
3 | import lombok.Data;
4 |
5 | @Data
6 | public class ProductRequest {
7 | private String name;
8 | private long price;
9 | private long quantity;
10 | }
11 |
--------------------------------------------------------------------------------
/ProductService/src/main/java/com/msbeigi/ProductService/model/ProductResponse.java:
--------------------------------------------------------------------------------
1 | package com.msbeigi.ProductService.model;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Builder;
5 | import lombok.Data;
6 | import lombok.NoArgsConstructor;
7 |
8 | @Data
9 | @AllArgsConstructor
10 | @NoArgsConstructor
11 | @Builder
12 | public class ProductResponse {
13 | private long productId;
14 | private String productName;
15 | private long quantity;
16 | private long price;
17 | }
18 |
--------------------------------------------------------------------------------
/ProductService/src/main/java/com/msbeigi/ProductService/repository/ProductRepository.java:
--------------------------------------------------------------------------------
1 | package com.msbeigi.ProductService.repository;
2 |
3 | import com.msbeigi.ProductService.entity.Product;
4 | import org.springframework.data.jpa.repository.JpaRepository;
5 | import org.springframework.stereotype.Repository;
6 |
7 | @Repository
8 | public interface ProductRepository extends JpaRepository {
9 | }
10 |
--------------------------------------------------------------------------------
/ProductService/src/main/java/com/msbeigi/ProductService/security/WebSecurityConfig.java:
--------------------------------------------------------------------------------
1 | package com.msbeigi.ProductService.security;
2 |
3 | import org.springframework.context.annotation.Bean;
4 | import org.springframework.context.annotation.Configuration;
5 | import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
6 | import org.springframework.security.config.annotation.web.builders.HttpSecurity;
7 | import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
8 | import org.springframework.security.config.annotation.web.configurers.oauth2.server.resource.OAuth2ResourceServerConfigurer;
9 | import org.springframework.security.web.SecurityFilterChain;
10 |
11 | @Configuration
12 | @EnableWebSecurity
13 | @EnableGlobalMethodSecurity(prePostEnabled = true)
14 | public class WebSecurityConfig {
15 | @Bean
16 | public SecurityFilterChain securityWebFilterChain(HttpSecurity httpSecurity) throws Exception {
17 | httpSecurity
18 | .authorizeRequests(authorizeRequest -> authorizeRequest
19 | .anyRequest()
20 | .authenticated()
21 | )
22 | .oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt);
23 |
24 | return httpSecurity.build();
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/ProductService/src/main/java/com/msbeigi/ProductService/services/ProductService.java:
--------------------------------------------------------------------------------
1 | package com.msbeigi.ProductService.services;
2 |
3 | import com.msbeigi.ProductService.model.ProductRequest;
4 | import com.msbeigi.ProductService.model.ProductResponse;
5 |
6 | public interface ProductService {
7 | long addProduct(ProductRequest productRequest);
8 |
9 | ProductResponse getProductById(long productId);
10 |
11 | void reduceQuantity(long productId, long quantity);
12 | }
13 |
--------------------------------------------------------------------------------
/ProductService/src/main/java/com/msbeigi/ProductService/services/ProductServiceImpl.java:
--------------------------------------------------------------------------------
1 | package com.msbeigi.ProductService.services;
2 |
3 | import com.msbeigi.ProductService.entity.Product;
4 | import com.msbeigi.ProductService.exception.ProductServiceCustomException;
5 | import com.msbeigi.ProductService.model.ProductRequest;
6 | import com.msbeigi.ProductService.model.ProductResponse;
7 | import com.msbeigi.ProductService.repository.ProductRepository;
8 | import lombok.extern.log4j.Log4j2;
9 | import org.springframework.beans.BeanUtils;
10 | import org.springframework.beans.factory.annotation.Autowired;
11 | import org.springframework.stereotype.Service;
12 |
13 | @Service
14 | @Log4j2
15 | public class ProductServiceImpl implements ProductService {
16 |
17 | @Autowired
18 | private ProductRepository productRepository;
19 |
20 | @Override
21 | public long addProduct(ProductRequest productRequest) {
22 | log.info("Adding product...");
23 | Product product =
24 | Product.builder()
25 | .productName(productRequest.getName())
26 | .price(productRequest.getPrice())
27 | .quantity(productRequest.getQuantity())
28 | .build();
29 |
30 | productRepository.save(product);
31 |
32 | log.info("Product with id: {} created.", product.getProductId());
33 | return product.getProductId();
34 | }
35 |
36 | @Override
37 | public ProductResponse getProductById(long productId) {
38 | log.info("Get the product for product id: {}", productId);
39 | Product product = productRepository.findById(productId).orElseThrow(
40 | () -> new ProductServiceCustomException("Product with id: " +
41 | productId + " is not exists.", "PRODUCT_NOT_FOUND"));
42 |
43 | ProductResponse productResponse = new ProductResponse();
44 | BeanUtils.copyProperties(product, productResponse);
45 |
46 | return productResponse;
47 | }
48 |
49 | @Override
50 | public void reduceQuantity(long productId, long quantity) {
51 | log.info("Reduce quantity {} for Id {}", quantity, productId);
52 |
53 | Product product = productRepository.findById(productId).orElseThrow(
54 | () -> new ProductServiceCustomException(
55 | "No product with id " + productId + " was found!",
56 | "NOT_FOUND"));
57 | if (product.getQuantity() < quantity) {
58 | throw new ProductServiceCustomException(
59 | "Product does not have sufficient quantity",
60 | "INSUFFICIENT_QUANTITY");
61 | }
62 |
63 | product.setQuantity(product.getQuantity() - quantity);
64 | productRepository.save(product);
65 |
66 | log.info("Product quantity updated successfully");
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/ProductService/src/main/resources/application.yaml:
--------------------------------------------------------------------------------
1 | server:
2 | port: 8080
3 |
4 | spring:
5 | datasource:
6 | url: jdbc:mysql://${DB_HOST:localhost}:3306/product_db
7 | username: root
8 | password: root
9 | driver-class-name: com.mysql.cj.jdbc.Driver
10 | jpa:
11 | database-platform: org.hibernate.dialect.MySQL57InnoDBDialect
12 | hibernate:
13 | ddl-auto: update
14 |
15 | application:
16 | name: PRODUCT-SERVICE
17 |
18 | config:
19 | import: configserver:${CONFIG_SERVER_URL:http://localhost:9296}
20 |
21 | #eureka:
22 | # instance:
23 | # prefer-ip-address: true
24 | # client:
25 | # fetch-registry: true
26 | # register-with-eureka: true
27 | # service-url:
28 | # defaultZone: ${EUREKA_SERVER_ADDRESS:http://localhost:8761/eureka}
29 |
--------------------------------------------------------------------------------
/ProductService/src/test/java/com/msbeigi/ProductService/ProductServiceApplicationTests.java:
--------------------------------------------------------------------------------
1 | package com.msbeigi.ProductService;
2 |
3 | import org.junit.jupiter.api.Test;
4 | import org.springframework.boot.test.context.SpringBootTest;
5 |
6 | @SpringBootTest
7 | class ProductServiceApplicationTests {
8 |
9 | @Test
10 | void contextLoads() {
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## An usefull repository for educational puposes in the concept of Spring Boot microservices.
2 | ### Fill free to contribute to the project.
3 |
--------------------------------------------------------------------------------
/ServiceRegistry/.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 |
--------------------------------------------------------------------------------
/ServiceRegistry/.mvn/wrapper/maven-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/msbeigiai/spring-boot-microservices/7c41c629c582ed45a45722b1ec1dba5fbe4574b3/ServiceRegistry/.mvn/wrapper/maven-wrapper.jar
--------------------------------------------------------------------------------
/ServiceRegistry/.mvn/wrapper/maven-wrapper.properties:
--------------------------------------------------------------------------------
1 | # Licensed to the Apache Software Foundation (ASF) under one
2 | # or more contributor license agreements. See the NOTICE file
3 | # distributed with this work for additional information
4 | # regarding copyright ownership. The ASF licenses this file
5 | # to you under the Apache License, Version 2.0 (the
6 | # "License"); you may not use this file except in compliance
7 | # with the License. You may obtain a copy of the License at
8 | #
9 | # https://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.7/apache-maven-3.8.7-bin.zip
18 | wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.1/maven-wrapper-3.1.1.jar
19 |
--------------------------------------------------------------------------------
/ServiceRegistry/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM openjdk:17
2 |
3 | ARG JAR_FILE=target/*.jar
4 |
5 | COPY ${JAR_FILE} serviceregistry.jar
6 |
7 | ENTRYPOINT ["java", "-jar", "/serviceregistry.jar"]
8 |
9 | EXPOSE 8761
10 |
11 |
--------------------------------------------------------------------------------
/ServiceRegistry/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 |
--------------------------------------------------------------------------------
/ServiceRegistry/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | org.springframework.boot
7 | spring-boot-starter-parent
8 | 2.7.12
9 |
10 |
11 | com.msbeigi
12 | ServiceRegistry
13 | 0.0.1
14 | ServiceRegistry
15 | Demo project for Spring Boot
16 |
17 | 17
18 | 2021.0.7
19 |
20 |
21 |
22 | org.springframework.cloud
23 | spring-cloud-starter
24 |
25 |
26 | org.springframework.cloud
27 | spring-cloud-starter-netflix-eureka-server
28 |
29 |
30 |
31 | org.springframework.boot
32 | spring-boot-starter-test
33 | test
34 |
35 |
36 |
37 |
38 |
39 | org.springframework.cloud
40 | spring-cloud-dependencies
41 | ${spring-cloud.version}
42 | pom
43 | import
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 | org.springframework.boot
52 | spring-boot-maven-plugin
53 |
54 |
55 | com.google.cloud.tools
56 | jib-maven-plugin
57 |
58 |
59 | openjdk:17
60 |
61 |
62 | registry.hub.docker.com/msbeigiai/serviceregistry
63 | ${project.version}
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
--------------------------------------------------------------------------------
/ServiceRegistry/src/main/java/com/msbeigi/serviceregistry/ServiceRegistryApplication.java:
--------------------------------------------------------------------------------
1 | package com.msbeigi.serviceregistry;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 | import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
6 |
7 | @SpringBootApplication
8 | @EnableEurekaServer
9 | public class ServiceRegistryApplication {
10 |
11 | public static void main(String[] args) {
12 | SpringApplication.run(ServiceRegistryApplication.class, args);
13 | }
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/ServiceRegistry/src/main/resources/application.yml:
--------------------------------------------------------------------------------
1 | server:
2 | port: 8761
3 |
4 | eureka:
5 | instance:
6 | hostname: "${HOSTNAME:localhost}.eureka"
7 | client:
8 | register-with-eureka: false
9 | fetch-registry: false
10 |
--------------------------------------------------------------------------------
/ServiceRegistry/src/test/java/com/msbeigi/serviceregistry/ServiceRegistryApplicationTests.java:
--------------------------------------------------------------------------------
1 | package com.msbeigi.serviceregistry;
2 |
3 | import org.junit.jupiter.api.Test;
4 | import org.springframework.boot.test.context.SpringBootTest;
5 |
6 | @SpringBootTest
7 | class ServiceRegistryApplicationTests {
8 |
9 | @Test
10 | void contextLoads() {
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '3'
2 | services:
3 | serviceregistry:
4 | image: 'msbeigiai/serviceregistry:0.0.1'
5 | container_name: serviceregistry
6 | ports:
7 | - '8761:8761'
8 |
9 | configserver:
10 | image: 'msbeigiai/configserver:0.0.1'
11 | container_name: configserver
12 | ports:
13 | - '9296:9296'
14 | healthcheck:
15 | test: ["CMD", "curl", "-f", "http://configserver:9296/actuator/health"]
16 | interval: 15s
17 | timeout: 10s
18 | retries: 5
19 | depends_on:
20 | - serviceregistry
21 | environment:
22 | - EUREKA_SERVER_ADDRESS=http://serviceregistry:8761/eureka
23 |
24 | cloudgateway:
25 | image: 'msbeigiai/cloudgateway:0.0.1'
26 | container_name: cloudgateway
27 | ports:
28 | - '9090:9090'
29 | depends_on:
30 | configserver:
31 | condition: service_healthy
32 | environment:
33 | - EUREKA_SERVER_ADDRESS=http://serviceregistry:8761/eureka
34 | - CONFIG_SERVER_URL=configserver
--------------------------------------------------------------------------------
/k8s-demo/deploy.yml:
--------------------------------------------------------------------------------
1 | apiVersion: apps/v1
2 | kind: Deployment
3 | metadata:
4 | name: service-registry
5 | spec:
6 | selector:
7 | matchLabels:
8 | app: service-registry
9 | template:
10 | metadata:
11 | labels:
12 | app: service-registry
13 | spec:
14 | containers:
15 | - name: service-registry
16 | image: msbeigiai/serviceregistry:0.0.1
17 | imagePullPolicy: Always
18 | ports:
19 | - containerPort: 8761
20 |
--------------------------------------------------------------------------------
/k8s-demo/svc.yml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | kind: Service
3 | metadata:
4 | name: serrvice-registry-svc
5 | spec:
6 | selector:
7 | app: service-registry
8 | ports:
9 | - port: 80
10 | targetPort: 8761
11 |
--------------------------------------------------------------------------------
/k8s/cloud-gateway-deployment.yml:
--------------------------------------------------------------------------------
1 | apiVersion: apps/v1
2 | kind: Deployment
3 | metadata:
4 | name: cloud-gateway-app
5 | spec:
6 | selector:
7 | matchLabels:
8 | app: cloud-gateway-app
9 | template:
10 | metadata:
11 | labels:
12 | app: cloud-gateway-app
13 | spec:
14 | containers:
15 | - name: cloud-gateway-app
16 | image: msbeigiai/cloudgateway:latest
17 | ports:
18 | - containerPort: 9090
19 | env:
20 | - name: EUREKA_SERVER_ADDRESS
21 | valueFrom:
22 | configMapKeyRef:
23 | key: eureka_service_address
24 | name: eureka-cm
25 | - name: CONFIG_SERVER_URL
26 | valueFrom:
27 | configMapKeyRef:
28 | key: config_url
29 | name: config-cm
30 | ---
31 |
32 | apiVersion: v1
33 | kind: Service
34 | metadata:
35 | name: cloud-gateway-svc
36 | spec:
37 | type: LoadBalancer
38 | selector:
39 | app: cloud-gateway-app
40 | ports:
41 | - port: 80
42 | targetPort: 9090
43 |
44 |
--------------------------------------------------------------------------------
/k8s/config-maps.yml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | kind: ConfigMap
3 | metadata:
4 | name: eureka-cm
5 | data:
6 | eureka_service_address: "http://eureka-0.eureka:8761/eureka"
7 |
8 | ---
9 |
10 | apiVersion: v1
11 | kind: ConfigMap
12 | metadata:
13 | name: config-cm
14 | data:
15 | config_url: "http://config-server-svc"
16 |
17 | ---
18 |
19 | apiVersion: v1
20 | kind: ConfigMap
21 | metadata:
22 | name: mysql-cm
23 | data:
24 | hostname: "mysql-0.mysql"
25 |
26 |
27 |
--------------------------------------------------------------------------------
/k8s/config-server-deployment.yml:
--------------------------------------------------------------------------------
1 | apiVersion: apps/v1
2 | kind: Deployment
3 | metadata:
4 | name: config-server-app
5 | spec:
6 | selector:
7 | matchLabels:
8 | app: config-server-app
9 | template:
10 | metadata:
11 | labels:
12 | app: config-server-app
13 | spec:
14 | containers:
15 | - name: config-server-app
16 | image: msbeigiai/configserver
17 | ports:
18 | - containerPort: 9296
19 | env:
20 | - name: EUREKA_SERVER_ADDRESS
21 | valueFrom:
22 | configMapKeyRef:
23 | name: eureka-cm
24 | key: eureka_service_address
25 |
26 | ---
27 |
28 | apiVersion: v1
29 | kind: Service
30 | metadata:
31 | name: config-server-svc
32 | spec:
33 | selector:
34 | app: config-server-app
35 | ports:
36 | - port: 80
37 | targetPort: 9296
38 |
39 |
--------------------------------------------------------------------------------
/k8s/mysql-deployment.yml:
--------------------------------------------------------------------------------
1 | # PV
2 | apiVersion: v1
3 | kind: PersistentVolume
4 | metadata:
5 | name: mysql-pv
6 | spec:
7 | capacity:
8 | storage: 1Gi
9 | accessModes:
10 | - ReadWriteOnce
11 | storageClassName: manual
12 | hostPath:
13 | path: "/mnt/data"
14 | type: DirectoryOrCreate
15 | ---
16 |
17 | # PVC
18 | apiVersion: v1
19 | kind: PersistentVolumeClaim
20 | metadata:
21 | name: mysql-pvc
22 | spec:
23 | resources:
24 | requests:
25 | storage: 1Gi
26 | storageClassName: manual
27 | accessModes:
28 | - ReadWriteOnce
29 | ---
30 |
31 | #StatefulSet - MySQL
32 | apiVersion: apps/v1
33 | kind: StatefulSet
34 | metadata:
35 | name: mysql
36 | spec:
37 | selector:
38 | matchLabels:
39 | app: mysql
40 | serviceName: mysql
41 | replicas: 1
42 | template:
43 | metadata:
44 | labels:
45 | app: mysql
46 | spec:
47 | containers:
48 | - name: mysql
49 | image: mysql:8.0
50 | ports:
51 | - containerPort: 3306
52 | name: mysql
53 | env:
54 | - name: MYSQL_ROOT_PASSWORD
55 | value: root
56 | volumeMounts:
57 | - name: mysql-initdb
58 | mountPath: /docker-entrypoint-initdb.d
59 | - name: mysql-persistent-storage
60 | mountPath: /var/lib/mysql
61 | volumes:
62 | - name: mysql-initdb
63 | configMap:
64 | name: mysql-initdb-cm
65 | - name: mysql-persistent-storage
66 | persistentVolumeClaim:
67 | claimName: mysql-pvc
68 | ---
69 |
70 | # Config
71 | apiVersion: v1
72 | kind: ConfigMap
73 | metadata:
74 | name: mysql-initdb-cm
75 | data:
76 | init.sql: |
77 | CREATE DATABASE IF NOT EXISTS order_db;
78 | CREATE DATABASE IF NOT EXISTS product_db;
79 | CREATE DATABASE IF NOT EXISTS payment_db;
80 |
81 |
82 | ---
83 |
84 | # Headless
85 | apiVersion: v1
86 | kind: Service
87 | metadata:
88 | name: mysql
89 | spec:
90 | clusterIP: None
91 | selector:
92 | app: mysql
93 | ports:
94 | - port: 3306
95 |
--------------------------------------------------------------------------------
/k8s/order-service-deployhment.yml:
--------------------------------------------------------------------------------
1 | apiVersion: apps/v1
2 | kind: Deployment
3 | metadata:
4 | name: order-service-app
5 | spec:
6 | selector:
7 | matchLabels:
8 | app: order-service-app
9 | template:
10 | metadata:
11 | labels:
12 | app: order-service-app
13 | spec:
14 | containers:
15 | - name: order-service-app
16 | image: msbeigiai/orderservice:latest
17 | ports:
18 | - containerPort: 8082
19 | env:
20 | - name: EUREKA_SERVER_ADDRESS
21 | valueFrom:
22 | configMapKeyRef:
23 | key: eureka_service_address
24 | name: eureka-cm
25 | - name: CONFIG_SERVER_URL
26 | valueFrom:
27 | configMapKeyRef:
28 | key: config_url
29 | name: config-cm
30 | - name: DB_HOST
31 | valueFrom:
32 | configMapKeyRef:
33 | key: hostname
34 | name: mysql-cm
35 |
36 | ---
37 |
38 | apiVersion: v1
39 | kind: Service
40 | metadata:
41 | name: order-service-svc
42 | spec:
43 | selector:
44 | app: order-service-app
45 | ports:
46 | - port: 80
47 | targetPort: 8082
48 |
--------------------------------------------------------------------------------
/k8s/payment-service-deployment.yml:
--------------------------------------------------------------------------------
1 | apiVersion: apps/v1
2 | kind: Deployment
3 | metadata:
4 | name: payment-service-app
5 | spec:
6 | selector:
7 | matchLabels:
8 | app: payment-service-app
9 | template:
10 | metadata:
11 | labels:
12 | app: payment-service-app
13 | spec:
14 | containers:
15 | - name: payment-service-app
16 | image: msbeigiai/paymentservice:latest
17 | ports:
18 | - containerPort: 8081
19 | env:
20 | - name: EUREKA_SERVER_ADDRESS
21 | valueFrom:
22 | configMapKeyRef:
23 | key: eureka_service_address
24 | name: eureka-cm
25 | - name: CONFIG_SERVER_URL
26 | valueFrom:
27 | configMapKeyRef:
28 | key: config_url
29 | name: config-cm
30 | - name: DB_HOST
31 | valueFrom:
32 | configMapKeyRef:
33 | key: hostname
34 | name: mysql-cm
35 | ---
36 |
37 | apiVersion: v1
38 | kind: Service
39 | metadata:
40 | name: payment-service-svc
41 | spec:
42 | selector:
43 | app: payment-service-app
44 | ports:
45 | - port: 80
46 | targetPort: 8081
47 |
48 |
--------------------------------------------------------------------------------
/k8s/product-service-deployment.yml:
--------------------------------------------------------------------------------
1 | apiVersion: apps/v1
2 | kind: Deployment
3 | metadata:
4 | name: product-service-app
5 | spec:
6 | selector:
7 | matchLabels:
8 | app: product-service-app
9 | template:
10 | metadata:
11 | labels:
12 | app: product-service-app
13 | spec:
14 | containers:
15 | - name: product-service-app
16 | image: msbeigiai/productservice:latest
17 | ports:
18 | - containerPort: 8080
19 | env:
20 | - name: EUREKA_SERVER_ADDRESS
21 | valueFrom:
22 | configMapKeyRef:
23 | key: eureka_service_address
24 | name: eureka-cm
25 | - name: CONFIG_SERVER_URL
26 | valueFrom:
27 | configMapKeyRef:
28 | key: config_url
29 | name: config-cm
30 | - name: DB_HOST
31 | valueFrom:
32 | configMapKeyRef:
33 | key: hostname
34 | name: mysql-cm
35 | ---
36 |
37 | apiVersion: v1
38 | kind: Service
39 | metadata:
40 | name: product-service-svc
41 | spec:
42 | selector:
43 | app: product-service-app
44 | ports:
45 | - port: 80
46 | targetPort: 8080
47 |
48 |
49 |
--------------------------------------------------------------------------------
/k8s/redis-deployment.yml:
--------------------------------------------------------------------------------
1 | apiVersion: apps/v1
2 | kind: Deployment
3 | metadata:
4 | name: redis-app
5 | spec:
6 | selector:
7 | matchLabels:
8 | app: redis-app
9 | template:
10 | metadata:
11 | labels:
12 | app: redis-app
13 | spec:
14 | containers:
15 | - name: redis-app
16 | image: redis:7.0.4
17 | ports:
18 | - containerPort: 6379
19 | command:
20 | - "redis-server"
21 | args:
22 | - "--protected-mode"
23 | - "no"
24 | ---
25 |
26 | apiVersion: v1
27 | kind: Service
28 | metadata:
29 | name: redis
30 | spec:
31 | selector:
32 | app: redis-app
33 | ports:
34 | - port: 6379
35 | targetPort: 6379
36 |
37 |
--------------------------------------------------------------------------------
/k8s/service-registry-statefulset.yml:
--------------------------------------------------------------------------------
1 | apiVersion: apps/v1
2 | kind: StatefulSet
3 | metadata:
4 | name: eureka
5 | spec:
6 | selector:
7 | matchLabels:
8 | app: eureka
9 | serviceName: eureka
10 | replicas: 1
11 | template:
12 | metadata:
13 | labels:
14 | app: eureka
15 | spec:
16 | containers:
17 | - name: eureka
18 | image: msbeigiai/serviceregistry:latest
19 | ports:
20 | - containerPort: 8761
21 |
22 | ---
23 |
24 | apiVersion: v1
25 | kind: Service
26 | metadata:
27 | name: eureak
28 | spec:
29 | clusterIP: None
30 | selector:
31 | app: eureka
32 | ports:
33 | - port: 8761
34 | name: eureka
35 |
36 | ---
37 |
38 | apiVersion: v1
39 | kind: Service
40 | metadata:
41 | name: eureak-lb
42 | spec:
43 | type: NodePort
44 | selector:
45 | app: eureak
46 | ports:
47 | - port: 80
48 | targetPort: 8761
49 |
50 |
51 |
--------------------------------------------------------------------------------
/k8s/zipkin-deployment.yml:
--------------------------------------------------------------------------------
1 | apiVersion: apps/v1
2 | kind: Deployment
3 | metadata:
4 | name: zipkin
5 | spec:
6 | selector:
7 | matchLabels:
8 | app: zipkin
9 | template:
10 | metadata:
11 | labels:
12 | app: zipkin
13 | spec:
14 | containers:
15 | - name: zipkin
16 | image: openzipkin/zipkin
17 | ports:
18 | - containerPort: 9411
19 | ---
20 |
21 | apiVersion: v1
22 | kind: Service
23 | metadata:
24 | name: zipkin-svc
25 | spec:
26 | selector:
27 | app: zipkin
28 | ports:
29 | - port: 9411
30 | targetPort: 9411
31 | ---
32 |
33 | apiVersion: v1
34 | kind: Service
35 | metadata:
36 | name: zipkin-lb-svc
37 | spec:
38 | type: LoadBalancer
39 | selector:
40 | app: zipkin
41 | ports:
42 | - port: 9411
43 | targetPort: 9411
44 |
45 |
--------------------------------------------------------------------------------