diff --git a/README.md b/README.md index c7e8ba0..4fe72bc 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,8 @@ # sd-workshop2 2022-1 sd workshop2 +Christian Gallo + - Completar la lógica de la applicación de pagos de tal manera que al hacer un pago através del microservicio de pagos, el monto de las facturas sea correctamente debitado, es decir, actualmente si una factura debe 1000 y yo hago un pago por 400 a esa factura, el microservicio invoice me sobreescribe el 1000 por 400 en vez de mostrarme el saldo restante 1000-400=600. - Completar la lógica de la aplicación de tal manera que haya 3 estados para las facturas. 0=debe 1=pagadoparcialmente 2=pagado - Hacer que las applicaciones se puedan registrar con consul @@ -8,4 +10,4 @@ sd workshop2 Bonus: - Subir las imagenes de la app a Docker hub -- Crear un script en bash que lance toda la aplicación. +- Crear un script en bash que lance toda la aplicación. \ No newline at end of file diff --git a/pay-app-spring-microservices/README.md b/pay-app-spring-microservices/README.md new file mode 100644 index 0000000..bc7c0ba --- /dev/null +++ b/pay-app-spring-microservices/README.md @@ -0,0 +1,25 @@ +# Microservicios con Spring Boot + +![Architecture](./resources/microservicesarchitecture.png) + +## Información de los microservicios +El microservicio de invoices, debe listar las facturas de clientes y además debe consumir una cola para cambiar el estado de la factura cuando esta se paga a través del microservicio de pago. +El microservicio de pago debe registrar el pago en su respectiva bd y además debe dejar un mensaje en una cola para actualizar la factura en el microservicio de facturas y además debe dejar un mensaje en una cola para registrar el movimiento en el microservicio de transacciones. +El microservicio de transacciones debe listar las transacciones de una factura, además debe consumir una cola para obtener las transacciones de pago del microservicio de pago. +Todos los microservicios deben consumir la cadena de conexión desde el servicio de configuración centralizada. + +La información de los endpoints disponibles por microservicio se incluyen en el documento de INFO.md +## Scripts de creación de bases de datos + +La informacion de como crear las bases de datos y sus respectivas tablas se incluyen en google.com + +## Tecnologías utilizadas + +- Spring Boot (Java Framework JDK v11+) +- Gradle (Gestor de dependencias) +- Postman (Test de endpoints/servicios rest) +- Postgresql (Base de Datos) +- MySQL (Base de Datos) +- MongoDB (Base de Datos NoSQL) +- Kafka (Gestor de Mensajería) +- Github (Repositorio para proyecto y Configuraciones de micorservicios) diff --git a/pay-app-spring-microservices/app-config/.gitignore b/pay-app-spring-microservices/app-config/.gitignore new file mode 100644 index 0000000..c2065bc --- /dev/null +++ b/pay-app-spring-microservices/app-config/.gitignore @@ -0,0 +1,37 @@ +HELP.md +.gradle +build/ +!gradle/wrapper/gradle-wrapper.jar +!**/src/main/**/build/ +!**/src/test/**/build/ + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache +bin/ +!**/src/main/**/bin/ +!**/src/test/**/bin/ + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr +out/ +!**/src/main/**/out/ +!**/src/test/**/out/ + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ + +### VS Code ### +.vscode/ diff --git a/pay-app-spring-microservices/app-config/Dockerfile b/pay-app-spring-microservices/app-config/Dockerfile new file mode 100644 index 0000000..03735c2 --- /dev/null +++ b/pay-app-spring-microservices/app-config/Dockerfile @@ -0,0 +1,13 @@ +FROM openjdk:13-alpine as stage1 +COPY . /app +WORKDIR /app +RUN chmod 777 gradlew +RUN ./gradlew clean +RUN ./gradlew bootJar + + +FROM openjdk:13-alpine +EXPOSE 8010 +COPY --from=stage1 /app/build/libs/app-config-1.0.0.jar app-config.jar +#ADD ./build/libs/app-config-1.0.0.jar app-config.jar +ENTRYPOINT ["java", "-jar", "/app-config.jar"] \ No newline at end of file diff --git a/pay-app-spring-microservices/app-config/build.gradle b/pay-app-spring-microservices/app-config/build.gradle new file mode 100644 index 0000000..59cffcd --- /dev/null +++ b/pay-app-spring-microservices/app-config/build.gradle @@ -0,0 +1,35 @@ +plugins { + id 'org.springframework.boot' version '2.3.10.RELEASE' + id 'io.spring.dependency-management' version '1.0.11.RELEASE' + id 'java' +} + +group = 'com.aforo' +version = '1.0.0' +sourceCompatibility = '11' + +repositories { + mavenCentral() +} + +ext { + set('springCloudVersion', "Hoxton.SR11") +} + +dependencies { + implementation 'org.springframework.cloud:spring-cloud-config-server' + + testImplementation('org.springframework.boot:spring-boot-starter-test') { + exclude group: 'org.junit.vintage', module: 'junit-vintage-engine' + } +} + +dependencyManagement { + imports { + mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}" + } +} + +test { + useJUnitPlatform() +} diff --git a/pay-app-spring-microservices/app-config/gradle/wrapper/gradle-wrapper.jar b/pay-app-spring-microservices/app-config/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..e708b1c Binary files /dev/null and b/pay-app-spring-microservices/app-config/gradle/wrapper/gradle-wrapper.jar differ diff --git a/pay-app-spring-microservices/app-config/gradle/wrapper/gradle-wrapper.properties b/pay-app-spring-microservices/app-config/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..549d844 --- /dev/null +++ b/pay-app-spring-microservices/app-config/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-6.9-bin.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/pay-app-spring-microservices/app-config/gradlew b/pay-app-spring-microservices/app-config/gradlew new file mode 100644 index 0000000..8f89047 --- /dev/null +++ b/pay-app-spring-microservices/app-config/gradlew @@ -0,0 +1,184 @@ +#!/usr/bin/env sh + +# +# Copyright 2015 the original author or authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ]; do + ls=$(ls -ld "$PRG") + link=$(expr "$ls" : '.*-> \(.*\)$') + if expr "$link" : '/.*' >/dev/null; then + PRG="$link" + else + PRG=$(dirname "$PRG")"/$link" + fi +done +SAVED="$(pwd)" +cd "$(dirname \"$PRG\")/" >/dev/null +APP_HOME="$(pwd -P)" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=$(basename "$0") + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn() { + echo "$*" +} + +die() { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$(uname)" in +CYGWIN*) + cygwin=true + ;; +Darwin*) + darwin=true + ;; +MINGW*) + msys=true + ;; +NONSTOP*) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ]; then + if [ -x "$JAVA_HOME/jre/sh/java" ]; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ]; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ]; then + MAX_FD_LIMIT=$(ulimit -H -n) + if [ $? -eq 0 ]; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ]; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ]; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin or MSYS, switch paths to Windows format before running java +if [ "$cygwin" = "true" -o "$msys" = "true" ]; then + APP_HOME=$(cygpath --path --mixed "$APP_HOME") + CLASSPATH=$(cygpath --path --mixed "$CLASSPATH") + + JAVACMD=$(cygpath --unix "$JAVACMD") + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=$(find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null) + SEP="" + for dir in $ROOTDIRSRAW; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ]; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@"; do + CHECK=$(echo "$arg" | egrep -c "$OURCYGPATTERN" -) + CHECK2=$(echo "$arg" | egrep -c "^-") ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ]; then ### Added a condition + eval $(echo args$i)=$(cygpath --path --ignore --mixed "$arg") + else + eval $(echo args$i)="\"$arg\"" + fi + i=$(expr $i + 1) + done + case $i in + 0) set -- ;; + 1) set -- "$args0" ;; + 2) set -- "$args0" "$args1" ;; + 3) set -- "$args0" "$args1" "$args2" ;; + 4) set -- "$args0" "$args1" "$args2" "$args3" ;; + 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save() { + for i; do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/"; done + echo " " +} +APP_ARGS=$(save "$@") + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +exec "$JAVACMD" "$@" diff --git a/pay-app-spring-microservices/app-config/gradlew.bat b/pay-app-spring-microservices/app-config/gradlew.bat new file mode 100644 index 0000000..107acd3 --- /dev/null +++ b/pay-app-spring-microservices/app-config/gradlew.bat @@ -0,0 +1,89 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/pay-app-spring-microservices/app-config/settings.gradle b/pay-app-spring-microservices/app-config/settings.gradle new file mode 100644 index 0000000..7c9d23a --- /dev/null +++ b/pay-app-spring-microservices/app-config/settings.gradle @@ -0,0 +1 @@ +rootProject.name = 'app-config' diff --git a/pay-app-spring-microservices/app-config/src/main/java/com/aforo/appconfig/AppConfigApplication.java b/pay-app-spring-microservices/app-config/src/main/java/com/aforo/appconfig/AppConfigApplication.java new file mode 100644 index 0000000..c64a6b2 --- /dev/null +++ b/pay-app-spring-microservices/app-config/src/main/java/com/aforo/appconfig/AppConfigApplication.java @@ -0,0 +1,15 @@ +package com.aforo.appconfig; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.config.server.EnableConfigServer; + +@SpringBootApplication +@EnableConfigServer +public class AppConfigApplication { + + public static void main(String[] args) { + SpringApplication.run(AppConfigApplication.class, args); + } + +} diff --git a/pay-app-spring-microservices/app-config/src/main/resources/application.properties b/pay-app-spring-microservices/app-config/src/main/resources/application.properties new file mode 100644 index 0000000..e7a2b58 --- /dev/null +++ b/pay-app-spring-microservices/app-config/src/main/resources/application.properties @@ -0,0 +1,15 @@ +# Server +spring.application.name=app-config +server.port=8888 + +# Config +spring.cloud.config.server.git.uri=https://github.com/Gallo9923/app-pay-config.git +spring.cloud.config.server.default-label=master +spring.cloud.config.server.git.search-paths=config +spring.cloud.config.server.git.skip-ssl-validation=true + +# Consul +# spring.cloud.consul.host=consul +# spring.cloud.consul.port=8500 +# spring.cloud.consul.discovery.health-check-interval=5s +# spring.cloud.consul.discovery.prefer-ip-address=true \ No newline at end of file diff --git a/pay-app-spring-microservices/app-config/src/test/java/com/aforo/appconfig/AppConfigApplicationTests.java b/pay-app-spring-microservices/app-config/src/test/java/com/aforo/appconfig/AppConfigApplicationTests.java new file mode 100644 index 0000000..90d6ce9 --- /dev/null +++ b/pay-app-spring-microservices/app-config/src/test/java/com/aforo/appconfig/AppConfigApplicationTests.java @@ -0,0 +1,13 @@ +package com.aforo.appconfig; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class AppConfigApplicationTests { + + @Test + void contextLoads() { + } + +} diff --git a/pay-app-spring-microservices/app-invoice/.gitignore b/pay-app-spring-microservices/app-invoice/.gitignore new file mode 100644 index 0000000..c2065bc --- /dev/null +++ b/pay-app-spring-microservices/app-invoice/.gitignore @@ -0,0 +1,37 @@ +HELP.md +.gradle +build/ +!gradle/wrapper/gradle-wrapper.jar +!**/src/main/**/build/ +!**/src/test/**/build/ + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache +bin/ +!**/src/main/**/bin/ +!**/src/test/**/bin/ + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr +out/ +!**/src/main/**/out/ +!**/src/test/**/out/ + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ + +### VS Code ### +.vscode/ diff --git a/pay-app-spring-microservices/app-invoice/Dockerfile b/pay-app-spring-microservices/app-invoice/Dockerfile new file mode 100644 index 0000000..529bfb1 --- /dev/null +++ b/pay-app-spring-microservices/app-invoice/Dockerfile @@ -0,0 +1,13 @@ +FROM openjdk:13-alpine as stage1 +COPY . /app +WORKDIR /app +RUN chmod 777 gradlew +RUN ./gradlew clean +RUN ./gradlew bootJar + + +FROM openjdk:13-alpine +EXPOSE 8010 +COPY --from=stage1 /app/build/libs/app-invoice-1.0.0.jar app-invoice.jar +#ADD ./build/libs/app-config-1.0.0.jar app-config.jar +ENTRYPOINT ["java", "-jar", "/app-invoice.jar"] \ No newline at end of file diff --git a/pay-app-spring-microservices/app-invoice/build.gradle b/pay-app-spring-microservices/app-invoice/build.gradle new file mode 100644 index 0000000..76d0556 --- /dev/null +++ b/pay-app-spring-microservices/app-invoice/build.gradle @@ -0,0 +1,47 @@ +plugins { + id 'org.springframework.boot' version '2.3.10.RELEASE' + id 'io.spring.dependency-management' version '1.0.11.RELEASE' + id 'java' +} + + +group = 'com.aforo' +version = '1.0.0' +sourceCompatibility = '11' + +configurations { + compileOnly { + extendsFrom annotationProcessor + } +} + +repositories { + mavenCentral() +} + +ext { + set('springCloudVersion', "Hoxton.SR11") +} + +dependencies { + implementation 'org.springframework.boot:spring-boot-starter-data-jpa' + implementation 'org.springframework.boot:spring-boot-starter-web' + implementation 'org.springframework.kafka:spring-kafka' + implementation 'org.springframework.cloud:spring-cloud-starter-config' + + compileOnly 'org.projectlombok:lombok' + runtimeOnly 'org.postgresql:postgresql' + annotationProcessor 'org.projectlombok:lombok' + testImplementation 'org.springframework.boot:spring-boot-starter-test' + testImplementation 'org.springframework.kafka:spring-kafka-test' +} + +dependencyManagement { + imports { + mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}" + } +} + +test { + useJUnitPlatform() +} diff --git a/pay-app-spring-microservices/app-invoice/gradle/wrapper/gradle-wrapper.jar b/pay-app-spring-microservices/app-invoice/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..e708b1c Binary files /dev/null and b/pay-app-spring-microservices/app-invoice/gradle/wrapper/gradle-wrapper.jar differ diff --git a/pay-app-spring-microservices/app-invoice/gradle/wrapper/gradle-wrapper.properties b/pay-app-spring-microservices/app-invoice/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..549d844 --- /dev/null +++ b/pay-app-spring-microservices/app-invoice/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-6.9-bin.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/pay-app-spring-microservices/app-invoice/gradlew b/pay-app-spring-microservices/app-invoice/gradlew new file mode 100644 index 0000000..8f89047 --- /dev/null +++ b/pay-app-spring-microservices/app-invoice/gradlew @@ -0,0 +1,184 @@ +#!/usr/bin/env sh + +# +# Copyright 2015 the original author or authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ]; do + ls=$(ls -ld "$PRG") + link=$(expr "$ls" : '.*-> \(.*\)$') + if expr "$link" : '/.*' >/dev/null; then + PRG="$link" + else + PRG=$(dirname "$PRG")"/$link" + fi +done +SAVED="$(pwd)" +cd "$(dirname \"$PRG\")/" >/dev/null +APP_HOME="$(pwd -P)" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=$(basename "$0") + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn() { + echo "$*" +} + +die() { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$(uname)" in +CYGWIN*) + cygwin=true + ;; +Darwin*) + darwin=true + ;; +MINGW*) + msys=true + ;; +NONSTOP*) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ]; then + if [ -x "$JAVA_HOME/jre/sh/java" ]; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ]; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ]; then + MAX_FD_LIMIT=$(ulimit -H -n) + if [ $? -eq 0 ]; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ]; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ]; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin or MSYS, switch paths to Windows format before running java +if [ "$cygwin" = "true" -o "$msys" = "true" ]; then + APP_HOME=$(cygpath --path --mixed "$APP_HOME") + CLASSPATH=$(cygpath --path --mixed "$CLASSPATH") + + JAVACMD=$(cygpath --unix "$JAVACMD") + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=$(find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null) + SEP="" + for dir in $ROOTDIRSRAW; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ]; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@"; do + CHECK=$(echo "$arg" | egrep -c "$OURCYGPATTERN" -) + CHECK2=$(echo "$arg" | egrep -c "^-") ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ]; then ### Added a condition + eval $(echo args$i)=$(cygpath --path --ignore --mixed "$arg") + else + eval $(echo args$i)="\"$arg\"" + fi + i=$(expr $i + 1) + done + case $i in + 0) set -- ;; + 1) set -- "$args0" ;; + 2) set -- "$args0" "$args1" ;; + 3) set -- "$args0" "$args1" "$args2" ;; + 4) set -- "$args0" "$args1" "$args2" "$args3" ;; + 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save() { + for i; do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/"; done + echo " " +} +APP_ARGS=$(save "$@") + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +exec "$JAVACMD" "$@" diff --git a/pay-app-spring-microservices/app-invoice/gradlew.bat b/pay-app-spring-microservices/app-invoice/gradlew.bat new file mode 100644 index 0000000..107acd3 --- /dev/null +++ b/pay-app-spring-microservices/app-invoice/gradlew.bat @@ -0,0 +1,89 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/pay-app-spring-microservices/app-invoice/settings.gradle b/pay-app-spring-microservices/app-invoice/settings.gradle new file mode 100644 index 0000000..e21d591 --- /dev/null +++ b/pay-app-spring-microservices/app-invoice/settings.gradle @@ -0,0 +1 @@ +rootProject.name = 'app-invoice' diff --git a/pay-app-spring-microservices/app-invoice/src/main/java/com/aforo/AppInvoiceApplication.java b/pay-app-spring-microservices/app-invoice/src/main/java/com/aforo/AppInvoiceApplication.java new file mode 100644 index 0000000..da591f6 --- /dev/null +++ b/pay-app-spring-microservices/app-invoice/src/main/java/com/aforo/AppInvoiceApplication.java @@ -0,0 +1,13 @@ +package com.aforo; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class AppInvoiceApplication { + + public static void main(String[] args) { + SpringApplication.run(AppInvoiceApplication.class, args); + } + +} diff --git a/pay-app-spring-microservices/app-invoice/src/main/java/com/aforo/controller/InvoiceController.java b/pay-app-spring-microservices/app-invoice/src/main/java/com/aforo/controller/InvoiceController.java new file mode 100644 index 0000000..9694557 --- /dev/null +++ b/pay-app-spring-microservices/app-invoice/src/main/java/com/aforo/controller/InvoiceController.java @@ -0,0 +1,29 @@ +package com.aforo.controller; + +import com.aforo.model.Invoice; +import com.aforo.service.InvoiceService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; + +@RestController +public class InvoiceController { + + @Autowired + private InvoiceService service; + + private Logger log = LoggerFactory.getLogger(InvoiceController.class); + + @GetMapping("/all") + public ResponseEntity> findAllInvoices() { + log.info("Consultando Invoices"); + var respose = service.findAllInvoices(); + return ResponseEntity.status(HttpStatus.CREATED).body(respose); + } +} diff --git a/pay-app-spring-microservices/app-invoice/src/main/java/com/aforo/dao/InvoiceDao.java b/pay-app-spring-microservices/app-invoice/src/main/java/com/aforo/dao/InvoiceDao.java new file mode 100644 index 0000000..b22452f --- /dev/null +++ b/pay-app-spring-microservices/app-invoice/src/main/java/com/aforo/dao/InvoiceDao.java @@ -0,0 +1,15 @@ +package com.aforo.dao; + +import com.aforo.model.Invoice; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.CrudRepository; +import org.springframework.stereotype.Repository; + +import java.util.List; + +@Repository +public interface InvoiceDao extends CrudRepository { + + @Query("select i from Invoice i order by i.idInvoice") + List findAllInvoices(); +} diff --git a/pay-app-spring-microservices/app-invoice/src/main/java/com/aforo/kafka/consumer/ConsumerConfig.java b/pay-app-spring-microservices/app-invoice/src/main/java/com/aforo/kafka/consumer/ConsumerConfig.java new file mode 100644 index 0000000..4c0b63d --- /dev/null +++ b/pay-app-spring-microservices/app-invoice/src/main/java/com/aforo/kafka/consumer/ConsumerConfig.java @@ -0,0 +1,9 @@ +package com.aforo.kafka.consumer; + +import org.springframework.context.annotation.Configuration; +import org.springframework.kafka.annotation.EnableKafka; + +@Configuration +@EnableKafka +public class ConsumerConfig { +} diff --git a/pay-app-spring-microservices/app-invoice/src/main/java/com/aforo/kafka/consumer/TransactionEvents.java b/pay-app-spring-microservices/app-invoice/src/main/java/com/aforo/kafka/consumer/TransactionEvents.java new file mode 100644 index 0000000..2f8c67f --- /dev/null +++ b/pay-app-spring-microservices/app-invoice/src/main/java/com/aforo/kafka/consumer/TransactionEvents.java @@ -0,0 +1,32 @@ +package com.aforo.kafka.consumer; + +import com.aforo.dao.InvoiceDao; +import com.aforo.model.Invoice; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.apache.kafka.clients.consumer.ConsumerRecord; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class TransactionEvents { + + @Autowired + private InvoiceDao _dao; + + @Autowired + private ObjectMapper objectMapper; + + private Logger log = LoggerFactory.getLogger(TransactionEvents.class); + + public void processTransactionEvent(ConsumerRecord consumerRecord) throws JsonProcessingException { + Invoice event = objectMapper.readValue(consumerRecord.value(), Invoice.class); + log.info("Actulizando Invoice ***" + event.getIdInvoice()); + event.setState(1); + log.info("Se ha pagado la factura # " + event.getIdInvoice()); + + _dao.save(event); + } +} diff --git a/pay-app-spring-microservices/app-invoice/src/main/java/com/aforo/kafka/listener/ConsumerListener.java b/pay-app-spring-microservices/app-invoice/src/main/java/com/aforo/kafka/listener/ConsumerListener.java new file mode 100644 index 0000000..29f4394 --- /dev/null +++ b/pay-app-spring-microservices/app-invoice/src/main/java/com/aforo/kafka/listener/ConsumerListener.java @@ -0,0 +1,27 @@ +package com.aforo.kafka.listener; + +import com.aforo.kafka.consumer.TransactionEvents; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonMappingException; +import org.apache.kafka.clients.consumer.ConsumerRecord; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.kafka.annotation.KafkaListener; +import org.springframework.stereotype.Component; + +@Component +public class ConsumerListener { + + @Autowired + private TransactionEvents events; + + private Logger log = LoggerFactory.getLogger(ConsumerListener.class); + + @KafkaListener(topics = {"transaction-events"}) + public void onMessage(ConsumerRecord consumerRecord) throws JsonMappingException, JsonProcessingException { + log.info("*************** MICROSERVICE APP INVOICE *******************"); + log.info("ConsumerRecord : {}", consumerRecord.value()); + events.processTransactionEvent(consumerRecord); + } +} diff --git a/pay-app-spring-microservices/app-invoice/src/main/java/com/aforo/model/Invoice.java b/pay-app-spring-microservices/app-invoice/src/main/java/com/aforo/model/Invoice.java new file mode 100644 index 0000000..bd907fd --- /dev/null +++ b/pay-app-spring-microservices/app-invoice/src/main/java/com/aforo/model/Invoice.java @@ -0,0 +1,18 @@ +package com.aforo.model; + +import lombok.Data; + +import javax.persistence.*; +import java.io.Serializable; + +@Entity +@Table(name="invoice") +@Data +public class Invoice implements Serializable { + + private static final long serialVersionUID = 1L; + @Id + private Integer idInvoice; + private Double amount ; + private Integer state ; +} diff --git a/pay-app-spring-microservices/app-invoice/src/main/java/com/aforo/service/InvoiceService.java b/pay-app-spring-microservices/app-invoice/src/main/java/com/aforo/service/InvoiceService.java new file mode 100644 index 0000000..f77a162 --- /dev/null +++ b/pay-app-spring-microservices/app-invoice/src/main/java/com/aforo/service/InvoiceService.java @@ -0,0 +1,19 @@ +package com.aforo.service; + +import com.aforo.dao.InvoiceDao; +import com.aforo.model.Invoice; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +public class InvoiceService { + + @Autowired + private InvoiceDao _dao; + + public List findAllInvoices() { + return _dao.findAllInvoices(); + } +} diff --git a/pay-app-spring-microservices/app-invoice/src/main/resources/application.properties b/pay-app-spring-microservices/app-invoice/src/main/resources/application.properties new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/pay-app-spring-microservices/app-invoice/src/main/resources/application.properties @@ -0,0 +1 @@ + diff --git a/pay-app-spring-microservices/app-invoice/src/main/resources/bootstrap.properties b/pay-app-spring-microservices/app-invoice/src/main/resources/bootstrap.properties new file mode 100644 index 0000000..dcc84c4 --- /dev/null +++ b/pay-app-spring-microservices/app-invoice/src/main/resources/bootstrap.properties @@ -0,0 +1,3 @@ +spring.application.name=app-invoice +spring.profiles.active=dev +spring.cloud.config.uri=http://${CONFIG_NODEPORT_SERVICE_SERVICE_HOST}:${CONFIG_NODEPORT_SERVICE_SERVICE_PORT} \ No newline at end of file diff --git a/pay-app-spring-microservices/app-invoice/src/test/java/com/aforo/AppInvoiceApplicationTests.java b/pay-app-spring-microservices/app-invoice/src/test/java/com/aforo/AppInvoiceApplicationTests.java new file mode 100644 index 0000000..faa2489 --- /dev/null +++ b/pay-app-spring-microservices/app-invoice/src/test/java/com/aforo/AppInvoiceApplicationTests.java @@ -0,0 +1,13 @@ +package com.aforo; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class AppInvoiceApplicationTests { + + @Test + void contextLoads() { + } + +} diff --git a/pay-app-spring-microservices/app-pay/.gitignore b/pay-app-spring-microservices/app-pay/.gitignore new file mode 100644 index 0000000..c2065bc --- /dev/null +++ b/pay-app-spring-microservices/app-pay/.gitignore @@ -0,0 +1,37 @@ +HELP.md +.gradle +build/ +!gradle/wrapper/gradle-wrapper.jar +!**/src/main/**/build/ +!**/src/test/**/build/ + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache +bin/ +!**/src/main/**/bin/ +!**/src/test/**/bin/ + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr +out/ +!**/src/main/**/out/ +!**/src/test/**/out/ + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ + +### VS Code ### +.vscode/ diff --git a/pay-app-spring-microservices/app-pay/Dockerfile b/pay-app-spring-microservices/app-pay/Dockerfile new file mode 100644 index 0000000..95034c5 --- /dev/null +++ b/pay-app-spring-microservices/app-pay/Dockerfile @@ -0,0 +1,13 @@ +FROM openjdk:13-alpine as stage1 +COPY . /app +WORKDIR /app +RUN chmod 777 gradlew +RUN ./gradlew clean +RUN ./gradlew bootJar + + +FROM openjdk:13-alpine +EXPOSE 8010 +COPY --from=stage1 /app/build/libs/app-pay-1.0.0.jar app-pay.jar +#ADD ./build/libs/app-config-1.0.0.jar app-config.jar +ENTRYPOINT ["java", "-jar", "/app-pay.jar"] \ No newline at end of file diff --git a/pay-app-spring-microservices/app-pay/README.md b/pay-app-spring-microservices/app-pay/README.md new file mode 100644 index 0000000..253df8a --- /dev/null +++ b/pay-app-spring-microservices/app-pay/README.md @@ -0,0 +1,12 @@ +# App Pay + +Microservicio encargado de registrar el pago de una factura y dejar un mensaje a la cola de kafka +para actualizar la factura desde el microservicio de app-invoice. También debe dejar un mensaje +para registrar el movimiento en el microservicio de transacciones. + +## Dependencias +* JPA (Hibernate) +* Apache Kafka +* Spring Cloud Config +* PostgreSQL +* Lombok diff --git a/pay-app-spring-microservices/app-pay/build.gradle b/pay-app-spring-microservices/app-pay/build.gradle new file mode 100644 index 0000000..fdaf2e0 --- /dev/null +++ b/pay-app-spring-microservices/app-pay/build.gradle @@ -0,0 +1,46 @@ +plugins { + id 'org.springframework.boot' version '2.3.10.RELEASE' + id 'io.spring.dependency-management' version '1.0.11.RELEASE' + id 'java' +} + +group = 'com.aforo' +version = '1.0.0' +sourceCompatibility = '11' + +configurations { + compileOnly { + extendsFrom annotationProcessor + } +} + +repositories { + mavenCentral() +} + +ext { + set('springCloudVersion', "Hoxton.SR11") +} + + +dependencies { + implementation 'org.springframework.boot:spring-boot-starter-data-jpa' + implementation 'org.springframework.boot:spring-boot-starter-web' + implementation 'org.springframework.kafka:spring-kafka' + implementation 'org.springframework.cloud:spring-cloud-starter-config' + compileOnly 'org.projectlombok:lombok' + runtimeOnly 'mysql:mysql-connector-java' + annotationProcessor 'org.projectlombok:lombok' + testImplementation 'org.springframework.boot:spring-boot-starter-test' + testImplementation 'org.springframework.kafka:spring-kafka-test' +} + +dependencyManagement { + imports { + mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}" + } +} + +test { + useJUnitPlatform() +} diff --git a/pay-app-spring-microservices/app-pay/gradle/wrapper/gradle-wrapper.jar b/pay-app-spring-microservices/app-pay/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..e708b1c Binary files /dev/null and b/pay-app-spring-microservices/app-pay/gradle/wrapper/gradle-wrapper.jar differ diff --git a/pay-app-spring-microservices/app-pay/gradle/wrapper/gradle-wrapper.properties b/pay-app-spring-microservices/app-pay/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..549d844 --- /dev/null +++ b/pay-app-spring-microservices/app-pay/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-6.9-bin.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/pay-app-spring-microservices/app-pay/gradlew b/pay-app-spring-microservices/app-pay/gradlew new file mode 100644 index 0000000..8f89047 --- /dev/null +++ b/pay-app-spring-microservices/app-pay/gradlew @@ -0,0 +1,184 @@ +#!/usr/bin/env sh + +# +# Copyright 2015 the original author or authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ]; do + ls=$(ls -ld "$PRG") + link=$(expr "$ls" : '.*-> \(.*\)$') + if expr "$link" : '/.*' >/dev/null; then + PRG="$link" + else + PRG=$(dirname "$PRG")"/$link" + fi +done +SAVED="$(pwd)" +cd "$(dirname \"$PRG\")/" >/dev/null +APP_HOME="$(pwd -P)" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=$(basename "$0") + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn() { + echo "$*" +} + +die() { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$(uname)" in +CYGWIN*) + cygwin=true + ;; +Darwin*) + darwin=true + ;; +MINGW*) + msys=true + ;; +NONSTOP*) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ]; then + if [ -x "$JAVA_HOME/jre/sh/java" ]; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ]; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ]; then + MAX_FD_LIMIT=$(ulimit -H -n) + if [ $? -eq 0 ]; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ]; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ]; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin or MSYS, switch paths to Windows format before running java +if [ "$cygwin" = "true" -o "$msys" = "true" ]; then + APP_HOME=$(cygpath --path --mixed "$APP_HOME") + CLASSPATH=$(cygpath --path --mixed "$CLASSPATH") + + JAVACMD=$(cygpath --unix "$JAVACMD") + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=$(find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null) + SEP="" + for dir in $ROOTDIRSRAW; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ]; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@"; do + CHECK=$(echo "$arg" | egrep -c "$OURCYGPATTERN" -) + CHECK2=$(echo "$arg" | egrep -c "^-") ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ]; then ### Added a condition + eval $(echo args$i)=$(cygpath --path --ignore --mixed "$arg") + else + eval $(echo args$i)="\"$arg\"" + fi + i=$(expr $i + 1) + done + case $i in + 0) set -- ;; + 1) set -- "$args0" ;; + 2) set -- "$args0" "$args1" ;; + 3) set -- "$args0" "$args1" "$args2" ;; + 4) set -- "$args0" "$args1" "$args2" "$args3" ;; + 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save() { + for i; do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/"; done + echo " " +} +APP_ARGS=$(save "$@") + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +exec "$JAVACMD" "$@" diff --git a/pay-app-spring-microservices/app-pay/gradlew.bat b/pay-app-spring-microservices/app-pay/gradlew.bat new file mode 100644 index 0000000..107acd3 --- /dev/null +++ b/pay-app-spring-microservices/app-pay/gradlew.bat @@ -0,0 +1,89 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/pay-app-spring-microservices/app-pay/settings.gradle b/pay-app-spring-microservices/app-pay/settings.gradle new file mode 100644 index 0000000..36f0da7 --- /dev/null +++ b/pay-app-spring-microservices/app-pay/settings.gradle @@ -0,0 +1 @@ +rootProject.name = 'app-pay' diff --git a/pay-app-spring-microservices/app-pay/src/main/java/com/aforo/AppPayApplication.java b/pay-app-spring-microservices/app-pay/src/main/java/com/aforo/AppPayApplication.java new file mode 100644 index 0000000..6a38973 --- /dev/null +++ b/pay-app-spring-microservices/app-pay/src/main/java/com/aforo/AppPayApplication.java @@ -0,0 +1,13 @@ +package com.aforo; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class AppPayApplication { + + public static void main(String[] args) { + SpringApplication.run(AppPayApplication.class, args); + } + +} diff --git a/pay-app-spring-microservices/app-pay/src/main/java/com/aforo/config/AutoCreateConfig.java b/pay-app-spring-microservices/app-pay/src/main/java/com/aforo/config/AutoCreateConfig.java new file mode 100644 index 0000000..9ef4dcf --- /dev/null +++ b/pay-app-spring-microservices/app-pay/src/main/java/com/aforo/config/AutoCreateConfig.java @@ -0,0 +1,19 @@ +package com.aforo.config; + +import org.apache.kafka.clients.admin.NewTopic; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.kafka.config.TopicBuilder; + +@Configuration +public class AutoCreateConfig { + + @Bean + public NewTopic depositEvent() { + return TopicBuilder + .name("trasaction-events") + .partitions(3) + .replicas(1) + .build(); + } +} diff --git a/pay-app-spring-microservices/app-pay/src/main/java/com/aforo/controller/PayController.java b/pay-app-spring-microservices/app-pay/src/main/java/com/aforo/controller/PayController.java new file mode 100644 index 0000000..d627039 --- /dev/null +++ b/pay-app-spring-microservices/app-pay/src/main/java/com/aforo/controller/PayController.java @@ -0,0 +1,36 @@ +package com.aforo.controller; + +import com.aforo.kafka.producer.PayEventProducer; +import com.aforo.model.Pay; +import com.aforo.service.PayService; +import com.fasterxml.jackson.core.JsonProcessingException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class PayController { + + @Autowired + private PayService service; + + @Autowired + PayEventProducer producer; + + private Logger log = LoggerFactory.getLogger(PayController.class); + + @PostMapping("/pay") + public ResponseEntity postDepositEvent(@RequestBody Pay pay) throws JsonProcessingException { + log.info("Registrando nuevo pago"); + var respose = service.registerPay(pay); + log.info("Enviando mensaje a Kafka"); + producer.sendPayEvent(respose); + log.info("Mensaje agregado a la cola correctamente"); + return ResponseEntity.status(HttpStatus.CREATED).body(respose); + } +} diff --git a/pay-app-spring-microservices/app-pay/src/main/java/com/aforo/dao/PayDao.java b/pay-app-spring-microservices/app-pay/src/main/java/com/aforo/dao/PayDao.java new file mode 100644 index 0000000..4a7ee91 --- /dev/null +++ b/pay-app-spring-microservices/app-pay/src/main/java/com/aforo/dao/PayDao.java @@ -0,0 +1,9 @@ +package com.aforo.dao; + +import com.aforo.model.Pay; +import org.springframework.data.repository.CrudRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface PayDao extends CrudRepository { +} diff --git a/pay-app-spring-microservices/app-pay/src/main/java/com/aforo/kafka/producer/PayEventProducer.java b/pay-app-spring-microservices/app-pay/src/main/java/com/aforo/kafka/producer/PayEventProducer.java new file mode 100644 index 0000000..1f970f4 --- /dev/null +++ b/pay-app-spring-microservices/app-pay/src/main/java/com/aforo/kafka/producer/PayEventProducer.java @@ -0,0 +1,73 @@ +package com.aforo.kafka.producer; + +import com.aforo.model.Pay; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.apache.kafka.clients.producer.ProducerRecord; +import org.apache.kafka.common.header.Header; +import org.apache.kafka.common.header.internals.RecordHeader; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.kafka.core.KafkaTemplate; +import org.springframework.kafka.support.SendResult; +import org.springframework.stereotype.Component; +import org.springframework.util.concurrent.ListenableFuture; +import org.springframework.util.concurrent.ListenableFutureCallback; + +import java.util.List; + + +@Component +public class PayEventProducer { + + @Autowired + private KafkaTemplate kafkaTemplate; + + @Autowired + private ObjectMapper objectMapper; + + private Logger log = LoggerFactory.getLogger(PayEventProducer.class); + String topic = "transaction-events"; + + public ListenableFuture> sendPayEvent(Pay pay) throws JsonProcessingException { + Integer key = pay.getIdOperation(); + String value = objectMapper.writeValueAsString(pay); + + ProducerRecord producerRecord = buildProducerRecord(key, value, topic); + ListenableFuture> listenableFuture = kafkaTemplate.send(producerRecord); + listenableFuture.addCallback(new ListenableFutureCallback<>() { + + @Override + public void onSuccess(SendResult result) { + handleSuccess(key, value, result); + } + + @Override + public void onFailure(Throwable ex) { + handleFailure(key, value, ex); + } + }); + + return listenableFuture; + } + + private ProducerRecord buildProducerRecord(Integer key, String value, String topic) { + List
recordHeaders = List.of(new RecordHeader("payment-event-source", "scanner".getBytes())); + return new ProducerRecord<>(topic, null, key, value, recordHeaders); + } + + private void handleFailure(Integer key, String value, Throwable e) { + log.error("Error enviando el mensaje, error: {} ", e.getMessage()); + try { + + } catch (Throwable ex) { + log.error("Error OnFailure: {}", ex.getMessage()); + } + } + + private void handleSuccess(Integer key, String value, SendResult result) { + log.info("Message Sent Successfully for the key :{} and the value is {},partition is {}", key, value, + result.getRecordMetadata().partition()); + } +} diff --git a/pay-app-spring-microservices/app-pay/src/main/java/com/aforo/model/Pay.java b/pay-app-spring-microservices/app-pay/src/main/java/com/aforo/model/Pay.java new file mode 100644 index 0000000..2379867 --- /dev/null +++ b/pay-app-spring-microservices/app-pay/src/main/java/com/aforo/model/Pay.java @@ -0,0 +1,24 @@ +package com.aforo.model; + +import lombok.Data; + +import javax.persistence.*; +import java.io.Serializable; +import java.util.Date; + +@Entity +@Table(name="pay") +@Data +public class Pay implements Serializable { + + private static final long serialVersionUID = 1L; + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "id_operation") + private Integer idOperation; + @Column(name = "id_invoice") + private Integer idInvoice; + private Double amount; + @Temporal(TemporalType.TIMESTAMP) + private Date dateTime; +} diff --git a/pay-app-spring-microservices/app-pay/src/main/java/com/aforo/service/PayService.java b/pay-app-spring-microservices/app-pay/src/main/java/com/aforo/service/PayService.java new file mode 100644 index 0000000..ae70de3 --- /dev/null +++ b/pay-app-spring-microservices/app-pay/src/main/java/com/aforo/service/PayService.java @@ -0,0 +1,17 @@ +package com.aforo.service; + +import com.aforo.dao.PayDao; +import com.aforo.model.Pay; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class PayService { + + @Autowired + private PayDao _dao; + + public Pay registerPay(Pay pay) { + return _dao.save(pay); + } +} diff --git a/pay-app-spring-microservices/app-pay/src/main/resources/application.properties b/pay-app-spring-microservices/app-pay/src/main/resources/application.properties new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/pay-app-spring-microservices/app-pay/src/main/resources/application.properties @@ -0,0 +1 @@ + diff --git a/pay-app-spring-microservices/app-pay/src/main/resources/bootstrap.properties b/pay-app-spring-microservices/app-pay/src/main/resources/bootstrap.properties new file mode 100644 index 0000000..c26f2eb --- /dev/null +++ b/pay-app-spring-microservices/app-pay/src/main/resources/bootstrap.properties @@ -0,0 +1,3 @@ +spring.application.name=app-pay +spring.profiles.active=dev +spring.cloud.config.uri=http://${CONFIG_NODEPORT_SERVICE_SERVICE_HOST}:${CONFIG_NODEPORT_SERVICE_SERVICE_PORT} diff --git a/pay-app-spring-microservices/app-pay/src/test/java/com/aforo/AppPayApplicationTests.java b/pay-app-spring-microservices/app-pay/src/test/java/com/aforo/AppPayApplicationTests.java new file mode 100644 index 0000000..d45f2ea --- /dev/null +++ b/pay-app-spring-microservices/app-pay/src/test/java/com/aforo/AppPayApplicationTests.java @@ -0,0 +1,13 @@ +package com.aforo; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class AppPayApplicationTests { + + @Test + void contextLoads() { + } + +} diff --git a/pay-app-spring-microservices/app-transaction/.gitignore b/pay-app-spring-microservices/app-transaction/.gitignore new file mode 100644 index 0000000..c2065bc --- /dev/null +++ b/pay-app-spring-microservices/app-transaction/.gitignore @@ -0,0 +1,37 @@ +HELP.md +.gradle +build/ +!gradle/wrapper/gradle-wrapper.jar +!**/src/main/**/build/ +!**/src/test/**/build/ + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache +bin/ +!**/src/main/**/bin/ +!**/src/test/**/bin/ + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr +out/ +!**/src/main/**/out/ +!**/src/test/**/out/ + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ + +### VS Code ### +.vscode/ diff --git a/pay-app-spring-microservices/app-transaction/Dockerfile b/pay-app-spring-microservices/app-transaction/Dockerfile new file mode 100644 index 0000000..a74e386 --- /dev/null +++ b/pay-app-spring-microservices/app-transaction/Dockerfile @@ -0,0 +1,13 @@ +FROM openjdk:13-alpine as stage1 +COPY . /app +WORKDIR /app +RUN chmod 777 gradlew +RUN ./gradlew clean +RUN ./gradlew bootJar + + +FROM openjdk:13-alpine +EXPOSE 8010 +COPY --from=stage1 /app/build/libs/app-transaction-1.0.0.jar app-transaction.jar +#ADD ./build/libs/app-config-1.0.0.jar app-config.jar +ENTRYPOINT ["java", "-jar", "/app-transaction.jar"] \ No newline at end of file diff --git a/pay-app-spring-microservices/app-transaction/build.gradle b/pay-app-spring-microservices/app-transaction/build.gradle new file mode 100644 index 0000000..1ca3403 --- /dev/null +++ b/pay-app-spring-microservices/app-transaction/build.gradle @@ -0,0 +1,44 @@ +plugins { + id 'org.springframework.boot' version '2.3.10.RELEASE' + id 'io.spring.dependency-management' version '1.0.11.RELEASE' + id 'java' +} + +group = 'com.aforo' +version = '1.0.0' +sourceCompatibility = '11' + +configurations { + compileOnly { + extendsFrom annotationProcessor + } +} + +repositories { + mavenCentral() +} + +ext { + set('springCloudVersion', "Hoxton.SR11") +} + +dependencies { + implementation 'org.springframework.boot:spring-boot-starter-data-mongodb' + implementation 'org.springframework.boot:spring-boot-starter-web' + implementation 'org.springframework.kafka:spring-kafka' + implementation 'org.springframework.cloud:spring-cloud-starter-config' + compileOnly 'org.projectlombok:lombok' + annotationProcessor 'org.projectlombok:lombok' + testImplementation 'org.springframework.boot:spring-boot-starter-test' + testImplementation 'org.springframework.kafka:spring-kafka-test' +} + +dependencyManagement { + imports { + mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}" + } +} + +test { + useJUnitPlatform() +} diff --git a/pay-app-spring-microservices/app-transaction/gradle/wrapper/gradle-wrapper.jar b/pay-app-spring-microservices/app-transaction/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..e708b1c Binary files /dev/null and b/pay-app-spring-microservices/app-transaction/gradle/wrapper/gradle-wrapper.jar differ diff --git a/pay-app-spring-microservices/app-transaction/gradle/wrapper/gradle-wrapper.properties b/pay-app-spring-microservices/app-transaction/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..549d844 --- /dev/null +++ b/pay-app-spring-microservices/app-transaction/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-6.9-bin.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/pay-app-spring-microservices/app-transaction/gradlew b/pay-app-spring-microservices/app-transaction/gradlew new file mode 100644 index 0000000..8f89047 --- /dev/null +++ b/pay-app-spring-microservices/app-transaction/gradlew @@ -0,0 +1,184 @@ +#!/usr/bin/env sh + +# +# Copyright 2015 the original author or authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ]; do + ls=$(ls -ld "$PRG") + link=$(expr "$ls" : '.*-> \(.*\)$') + if expr "$link" : '/.*' >/dev/null; then + PRG="$link" + else + PRG=$(dirname "$PRG")"/$link" + fi +done +SAVED="$(pwd)" +cd "$(dirname \"$PRG\")/" >/dev/null +APP_HOME="$(pwd -P)" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=$(basename "$0") + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn() { + echo "$*" +} + +die() { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$(uname)" in +CYGWIN*) + cygwin=true + ;; +Darwin*) + darwin=true + ;; +MINGW*) + msys=true + ;; +NONSTOP*) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ]; then + if [ -x "$JAVA_HOME/jre/sh/java" ]; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ]; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ]; then + MAX_FD_LIMIT=$(ulimit -H -n) + if [ $? -eq 0 ]; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ]; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ]; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin or MSYS, switch paths to Windows format before running java +if [ "$cygwin" = "true" -o "$msys" = "true" ]; then + APP_HOME=$(cygpath --path --mixed "$APP_HOME") + CLASSPATH=$(cygpath --path --mixed "$CLASSPATH") + + JAVACMD=$(cygpath --unix "$JAVACMD") + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=$(find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null) + SEP="" + for dir in $ROOTDIRSRAW; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ]; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@"; do + CHECK=$(echo "$arg" | egrep -c "$OURCYGPATTERN" -) + CHECK2=$(echo "$arg" | egrep -c "^-") ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ]; then ### Added a condition + eval $(echo args$i)=$(cygpath --path --ignore --mixed "$arg") + else + eval $(echo args$i)="\"$arg\"" + fi + i=$(expr $i + 1) + done + case $i in + 0) set -- ;; + 1) set -- "$args0" ;; + 2) set -- "$args0" "$args1" ;; + 3) set -- "$args0" "$args1" "$args2" ;; + 4) set -- "$args0" "$args1" "$args2" "$args3" ;; + 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save() { + for i; do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/"; done + echo " " +} +APP_ARGS=$(save "$@") + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +exec "$JAVACMD" "$@" diff --git a/pay-app-spring-microservices/app-transaction/gradlew.bat b/pay-app-spring-microservices/app-transaction/gradlew.bat new file mode 100644 index 0000000..107acd3 --- /dev/null +++ b/pay-app-spring-microservices/app-transaction/gradlew.bat @@ -0,0 +1,89 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/pay-app-spring-microservices/app-transaction/settings.gradle b/pay-app-spring-microservices/app-transaction/settings.gradle new file mode 100644 index 0000000..22a90a6 --- /dev/null +++ b/pay-app-spring-microservices/app-transaction/settings.gradle @@ -0,0 +1 @@ +rootProject.name = 'app-transaction' diff --git a/pay-app-spring-microservices/app-transaction/src/main/java/com/aforo/AppTransactionApplication.java b/pay-app-spring-microservices/app-transaction/src/main/java/com/aforo/AppTransactionApplication.java new file mode 100644 index 0000000..83b1bf1 --- /dev/null +++ b/pay-app-spring-microservices/app-transaction/src/main/java/com/aforo/AppTransactionApplication.java @@ -0,0 +1,13 @@ +package com.aforo; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class AppTransactionApplication { + + public static void main(String[] args) { + SpringApplication.run(AppTransactionApplication.class, args); + } + +} diff --git a/pay-app-spring-microservices/app-transaction/src/main/java/com/aforo/controller/TransactionController.java b/pay-app-spring-microservices/app-transaction/src/main/java/com/aforo/controller/TransactionController.java new file mode 100644 index 0000000..ed44a2d --- /dev/null +++ b/pay-app-spring-microservices/app-transaction/src/main/java/com/aforo/controller/TransactionController.java @@ -0,0 +1,29 @@ +package com.aforo.controller; + +import com.aforo.model.Transaction; +import com.aforo.service.TransactionService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; + +@RestController +public class TransactionController { + + @Autowired + private TransactionService service; + + private Logger log = LoggerFactory.getLogger(TransactionController.class); + + @GetMapping("/all") + public ResponseEntity> findAllInvoices() { + log.info("Consultando Invoices"); + var respose = service.findAllTransaction(); + return ResponseEntity.status(HttpStatus.CREATED).body(respose); + } +} diff --git a/pay-app-spring-microservices/app-transaction/src/main/java/com/aforo/dao/TransactionDao.java b/pay-app-spring-microservices/app-transaction/src/main/java/com/aforo/dao/TransactionDao.java new file mode 100644 index 0000000..bb01f57 --- /dev/null +++ b/pay-app-spring-microservices/app-transaction/src/main/java/com/aforo/dao/TransactionDao.java @@ -0,0 +1,9 @@ +package com.aforo.dao; + +import com.aforo.model.Transaction; +import org.springframework.data.mongodb.repository.MongoRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface TransactionDao extends MongoRepository { +} diff --git a/pay-app-spring-microservices/app-transaction/src/main/java/com/aforo/kafka/consumer/ConsumerConfig.java b/pay-app-spring-microservices/app-transaction/src/main/java/com/aforo/kafka/consumer/ConsumerConfig.java new file mode 100644 index 0000000..4c0b63d --- /dev/null +++ b/pay-app-spring-microservices/app-transaction/src/main/java/com/aforo/kafka/consumer/ConsumerConfig.java @@ -0,0 +1,9 @@ +package com.aforo.kafka.consumer; + +import org.springframework.context.annotation.Configuration; +import org.springframework.kafka.annotation.EnableKafka; + +@Configuration +@EnableKafka +public class ConsumerConfig { +} diff --git a/pay-app-spring-microservices/app-transaction/src/main/java/com/aforo/kafka/consumer/TransactionEvents.java b/pay-app-spring-microservices/app-transaction/src/main/java/com/aforo/kafka/consumer/TransactionEvents.java new file mode 100644 index 0000000..3e54492 --- /dev/null +++ b/pay-app-spring-microservices/app-transaction/src/main/java/com/aforo/kafka/consumer/TransactionEvents.java @@ -0,0 +1,29 @@ +package com.aforo.kafka.consumer; + +import com.aforo.dao.TransactionDao; +import com.aforo.model.Transaction; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.apache.kafka.clients.consumer.ConsumerRecord; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class TransactionEvents { + + @Autowired + private TransactionDao _dao; + + @Autowired + private ObjectMapper objectMapper; + + private Logger log = LoggerFactory.getLogger(TransactionEvents.class); + + public void processTransactionEvent(ConsumerRecord consumerRecord) throws JsonProcessingException { + Transaction event = objectMapper.readValue(consumerRecord.value(), Transaction.class); + log.info("Registrando Transaccion Invoice ***" + event.getIdInvoice()); + _dao.save(event); + } +} diff --git a/pay-app-spring-microservices/app-transaction/src/main/java/com/aforo/kafka/listener/ConsumerListener.java b/pay-app-spring-microservices/app-transaction/src/main/java/com/aforo/kafka/listener/ConsumerListener.java new file mode 100644 index 0000000..f82cbd5 --- /dev/null +++ b/pay-app-spring-microservices/app-transaction/src/main/java/com/aforo/kafka/listener/ConsumerListener.java @@ -0,0 +1,27 @@ +package com.aforo.kafka.listener; + +import com.aforo.kafka.consumer.TransactionEvents; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonMappingException; +import org.apache.kafka.clients.consumer.ConsumerRecord; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.kafka.annotation.KafkaListener; +import org.springframework.stereotype.Component; + +@Component +public class ConsumerListener { + + @Autowired + private TransactionEvents events; + + private Logger log = LoggerFactory.getLogger(ConsumerListener.class); + + @KafkaListener(topics = {"transaction-events"}) + public void onMessage(ConsumerRecord consumerRecord) throws JsonMappingException, JsonProcessingException { + log.info("*************** MICROSERVICE APP TRANSACTION *******************"); + log.info("ConsumerRecord : {}", consumerRecord.value()); + events.processTransactionEvent(consumerRecord); + } +} diff --git a/pay-app-spring-microservices/app-transaction/src/main/java/com/aforo/model/Transaction.java b/pay-app-spring-microservices/app-transaction/src/main/java/com/aforo/model/Transaction.java new file mode 100644 index 0000000..1b4dcfb --- /dev/null +++ b/pay-app-spring-microservices/app-transaction/src/main/java/com/aforo/model/Transaction.java @@ -0,0 +1,20 @@ +package com.aforo.model; + +import lombok.Data; +import org.bson.codecs.pojo.annotations.BsonId; +import org.springframework.data.mongodb.core.mapping.Document; + +import java.io.Serializable; +import java.util.Date; + +@Document +@Data +public class Transaction implements Serializable { + + private static final long serialVersionUID = 1L; + @BsonId + private String idTransaction; + private Integer idInvoice; + private Double amount ; + private Date dateTime; +} diff --git a/pay-app-spring-microservices/app-transaction/src/main/java/com/aforo/service/TransactionService.java b/pay-app-spring-microservices/app-transaction/src/main/java/com/aforo/service/TransactionService.java new file mode 100644 index 0000000..e92eb45 --- /dev/null +++ b/pay-app-spring-microservices/app-transaction/src/main/java/com/aforo/service/TransactionService.java @@ -0,0 +1,19 @@ +package com.aforo.service; + +import com.aforo.dao.TransactionDao; +import com.aforo.model.Transaction; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +public class TransactionService { + + @Autowired + private TransactionDao _dao; + + public List findAllTransaction() { + return _dao.findAll(); + } +} diff --git a/pay-app-spring-microservices/app-transaction/src/main/resources/application.properties b/pay-app-spring-microservices/app-transaction/src/main/resources/application.properties new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/pay-app-spring-microservices/app-transaction/src/main/resources/application.properties @@ -0,0 +1 @@ + diff --git a/pay-app-spring-microservices/app-transaction/src/main/resources/bootstrap.properties b/pay-app-spring-microservices/app-transaction/src/main/resources/bootstrap.properties new file mode 100644 index 0000000..79922d4 --- /dev/null +++ b/pay-app-spring-microservices/app-transaction/src/main/resources/bootstrap.properties @@ -0,0 +1,3 @@ +spring.application.name=app-transaction +spring.profiles.active=dev +spring.cloud.config.uri=http://${CONFIG_NODEPORT_SERVICE_SERVICE_HOST}:${CONFIG_NODEPORT_SERVICE_SERVICE_PORT} diff --git a/pay-app-spring-microservices/app-transaction/src/test/java/com/aforo/AppTransactionApplicationTests.java b/pay-app-spring-microservices/app-transaction/src/test/java/com/aforo/AppTransactionApplicationTests.java new file mode 100644 index 0000000..9416622 --- /dev/null +++ b/pay-app-spring-microservices/app-transaction/src/test/java/com/aforo/AppTransactionApplicationTests.java @@ -0,0 +1,13 @@ +package com.aforo; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class AppTransactionApplicationTests { + + @Test + void contextLoads() { + } + +} diff --git a/pay-app-spring-microservices/appgw/gateway.config.yml b/pay-app-spring-microservices/appgw/gateway.config.yml new file mode 100644 index 0000000..1a7f68b --- /dev/null +++ b/pay-app-spring-microservices/appgw/gateway.config.yml @@ -0,0 +1,35 @@ +http: + port: 8080 +admin: + port: 9876 + host: localhost +apiEndpoints: + appconfig: + host: localhost + paths: ['/config','/config/*'] +serviceEndpoints: + appconfig: + url: 'http://loadbalancer/config/' +policies: + - basic-auth + - cors + - expression + - key-auth + - log + - oauth2 + - proxy + - rate-limit +pipelines: + default: + apiEndpoints: + - appconfig + policies: + # Uncomment `key-auth:` when instructed to in the Getting Started guide. + - key-auth: + - proxy: + - action: + serviceEndpoint: appconfig + changeOrigin: true + prependPath: false + ignorePath: false + stripPath: false diff --git a/pay-app-spring-microservices/appgw/models/applications.json b/pay-app-spring-microservices/appgw/models/applications.json new file mode 100644 index 0000000..8b9c248 --- /dev/null +++ b/pay-app-spring-microservices/appgw/models/applications.json @@ -0,0 +1,16 @@ +{ + "$id": "http://express-gateway.io/models/applications.json", + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "redirectUri": { + "type": "string", + "format": "uri" + } + }, + "required": [ + "name" + ] +} diff --git a/pay-app-spring-microservices/appgw/models/credentials.json b/pay-app-spring-microservices/appgw/models/credentials.json new file mode 100644 index 0000000..3762505 --- /dev/null +++ b/pay-app-spring-microservices/appgw/models/credentials.json @@ -0,0 +1,85 @@ +{ + "$id": "http://express-gateway.io/models/credentials.json", + "type": "object", + "definitions": { + "credentialBase": { + "type": "object", + "properties": { + "autoGeneratePassword": { + "type": "boolean", + "default": true + }, + "scopes": { + "type": [ + "string", + "array" + ], + "items": { + "type": "string" + } + } + }, + "required": [ + "autoGeneratePassword" + ] + } + }, + "properties": { + "basic-auth": { + "allOf": [ + { + "$ref": "#/definitions/credentialBase" + }, + { + "type": "object", + "properties": { + "passwordKey": { + "type": "string", + "default": "password" + } + }, + "required": [ + "passwordKey" + ] + } + ] + }, + "key-auth": { + "type": "object", + "properties": { + "scopes": { + "type": [ + "string", + "array" + ], + "items": { + "type": "string" + } + } + } + }, + "jwt": { + "type": "object", + "properties": {} + }, + "oauth2": { + "allOf": [ + { + "$ref": "#/definitions/credentialBase" + }, + { + "type": "object", + "properties": { + "passwordKey": { + "type": "string", + "default": "secret" + } + }, + "required": [ + "passwordKey" + ] + } + ] + } + } +} diff --git a/pay-app-spring-microservices/appgw/models/users.json b/pay-app-spring-microservices/appgw/models/users.json new file mode 100644 index 0000000..0ad047f --- /dev/null +++ b/pay-app-spring-microservices/appgw/models/users.json @@ -0,0 +1,28 @@ +{ + "$id": "http://express-gateway.io/models/users.json", + "type": "object", + "properties": { + "firstname": { + "type": "string" + }, + "lastname": { + "type": "string" + }, + "username": { + "type": "string" + }, + "email": { + "type": "string", + "format": "email" + }, + "redirectUri": { + "type": "string", + "format": "uri" + } + }, + "required": [ + "username", + "firstname", + "lastname" + ] +} diff --git a/pay-app-spring-microservices/appgw/system.config.yml b/pay-app-spring-microservices/appgw/system.config.yml new file mode 100644 index 0000000..7f3e32a --- /dev/null +++ b/pay-app-spring-microservices/appgw/system.config.yml @@ -0,0 +1,27 @@ +# Core +db: + redis: + host: express-gateway-data-store + port: 6379 + namespace: EG + +#plugins: + # express-gateway-plugin-example: + # param1: 'param from system.config' + +crypto: + cipherKey: sensitiveKey + algorithm: aes256 + saltRounds: 10 + +# OAuth2 Settings +session: + secret: keyboard cat + resave: false + saveUninitialized: false +accessTokens: + timeToExpiry: 7200000 +refreshTokens: + timeToExpiry: 7200000 +authorizationCodes: + timeToExpiry: 300000 diff --git a/pay-app-spring-microservices/commands.md b/pay-app-spring-microservices/commands.md new file mode 100644 index 0000000..4c7fa26 --- /dev/null +++ b/pay-app-spring-microservices/commands.md @@ -0,0 +1,98 @@ +docker network create distribuidos +docker run -p 5432:5432 --name postgres --network distribuidos -e POSTGRES_PASSWORD=postgres -e POSTGRES_DB=db_invoice -d icesiops/postgres:0.1.0 + +docker run -p 3306:3306 --name mysql --network distribuidos -e MYSQL_ROOT_PASSWORD=mysql -e MYSQL_DATABASE=db_operation -d icesiops/mysql:0.1.0 + +docker run -p 27017:27017 --network distribuidos --name mongodb -d mongo + +docker run -p 2181:2181 -d -p 9092:9092 --name servicekafka --network distribuidos -e ADVERTISED_HOST=servicekafka -e NUM_PARTITIONS=3 johnnypark/kafka-zookeeper + +docker run -d -p 8888:8888 --network distribuidos --name app-config icesiops/appconfig:0.1.0 + +docker run -d -p 8006:8006 --network distribuidos --name app-invoice icesiops/appinvoice:0.1.0 + +docker run -d -p 8010:8010 --network distribuidos --name app-pay icesiops/apppay:0.1.0 + +docker run -d -p 8082:8082 --network distribuidos --name app-transaction icesiops/apptransaction:0.1.0 + +psql -h localhost -d db_invoice -U postgres -f data.sql + +#### consul + +Modify application.properties file according to consul server information. +Add the line implementation 'org.springframework.cloud:spring-cloud-starter-consul-discovery' into build.gradle depedencies +Install dnsmasq +Create a config file for dnsmasq below the path /etc/dnsmasq.d +Add the next line server=/consul/127.0.0.1#8600 +start dnsmasq +modifiy resolv.conf to add ip loopback like dns server +run command: dig app-service.service.consul + +docker run -d -p 8500:8500 -p 8600:8600/udp --network distribuidos --name consul consul:latest agent -server -bootstrap-expect 1 -ui -data-dir /tmp -client=0.0.0.0 + +### Load Balancer +Create dockerfile +FROM haproxy:2.3 +COPY haproxy.cfg /usr/local/etc/haproxy/haproxy.cfg + +Create haproxy config +defaults + timeout connect 5s + timeout client 1m + timeout server 1m + +frontend stats + bind *:1936 + mode http + stats uri / + stats show-legends + no log + +frontend http_front + bind *:80 + default_backend http_back + +backend http_back + balance roundrobin + server-template mywebapp 1-10 _web._tcp.service.consul resolvers consul resolve-opts allow-dup-ip resolve-prefer ipv4 check + +resolvers consul + nameserver consul 127.0.0.1:8600 + accepted_payload_size 8192 + hold valid 5s + +docker build -t icesiops/loadbalancer:0.1.0 . + +### Application Gateway + +In order to use Identity features, we need to have a data storage like Redis. + +docker run --network distribuidos -d --name express-gateway-data-store \ + -p 6379:6379 \ + redis:alpine +2. Start the Express-Gateway instance +Run the command inside appgw directory o keep in mind change the volume path to pointing to gateway.config.yml +docker run -d --name express-gateway \ + --network distribuidos \ + -v .:/var/lib/eg \ + -p 8080:8080 \ + -p 9876:9876 \ + express-gateway + +3. uncoment #key-auth +4. connect to gw container +docker exec -it express-gateway sh + +5. create users +eg users create + +6. assign auth key +eg credentials create -c sebas -t key-auth -q + +7. copy key 3DvE2HCfZCyfgxAjF40tOk:2U4Cojm11JaPJF6WRUcFBL + +8. Curl API endpoint as Sebas with key credentials - SUCCESS! + +curl -H "Authorization: apiKey ${keyId}:${keySecret}" http://localhost:8080/config/app-pay/dev + +curl -H "Authorization: apiKey 3DvE2HCfZCyfgxAjF40tOk:2U4Cojm11JaPJF6WRUcFBL" http://localhost:8080/config/app-pay/dev diff --git a/pay-app-spring-microservices/config/app-invoice-dev.properties b/pay-app-spring-microservices/config/app-invoice-dev.properties new file mode 100644 index 0000000..2b50446 --- /dev/null +++ b/pay-app-spring-microservices/config/app-invoice-dev.properties @@ -0,0 +1,25 @@ +# Server +spring.application.name=app-invoice +server.port=8006 + +# Kafka +spring.kafka.consumer.bootstrap-servers=${KAFKA_SERVICE_SERVICE_HOST}:${KAFKA_SERVICE_SERVICE_PORT_IDK} +#spring.kafka.consumer.bootstrap-servers=servicekafka:9092 +spring.kafka.admin.properties.bootstrap.servers=${KAFKA_SERVICE_SERVICE_HOST}:${KAFKA_SERVICE_SERVICE_PORT_IDK} +#spring.kafka.admin.properties.bootstrap.servers=servicekafka:9092 +spring.kafka.consumer.key-deserializer=org.apache.kafka.common.serialization.IntegerDeserializer +spring.kafka.consumer.value-deserializer=org.apache.kafka.common.serialization.StringDeserializer +spring.kafka.consumer.group-id=invoice-events-listener-group + +# JPA +logging.level.org.hibernate.SQL=debug +spring.jpa.properties.hibernate.enable_lazy_load_no_trans=true +spring.jpa.hibernate.ddl-auto=create + +# Postgresql +spring.datasource.url=jdbc:postgresql://${DB_INVOICE_CLUSTERIP_SERVICE_SERVICE_HOST}:${DB_INVOICE_CLUSTERIP_SERVICE_SERVICE_PORT}/db_invoice +#spring.datasource.url=jdbc:postgresql://postgres:5432/db_invoice +spring.datasource.username=postgres +spring.datasource.password=postgres +spring.datasource.driver-class-name=org.postgresql.Driver +spring.jpa.database-platform=org.hibernate.dialect.PostgreSQL95Dialect \ No newline at end of file diff --git a/pay-app-spring-microservices/config/app-pay-dev.properties b/pay-app-spring-microservices/config/app-pay-dev.properties new file mode 100644 index 0000000..7569860 --- /dev/null +++ b/pay-app-spring-microservices/config/app-pay-dev.properties @@ -0,0 +1,25 @@ +# Server +spring.application.name=app-pay +server.port=8010 + +# Kafka +spring.kafka.template.default-topic=transaction-events +spring.kafka.producer.bootstrap-servers=${KAFKA_SERVICE_SERVICE_HOST}:${KAFKA_SERVICE_SERVICE_PORT_IDK} +#spring.kafka.producer.bootstrap-servers=servicekafka:9092 +spring.kafka.producer.key-serializer=org.apache.kafka.common.serialization.IntegerSerializer +spring.kafka.producer.value-serializer=org.apache.kafka.common.serialization.StringSerializer +spring.kafka.admin.properties.bootstrap.servers=${KAFKA_SERVICE_SERVICE_HOST}:${KAFKA_SERVICE_SERVICE_PORT_IDK} +#spring.kafka.admin.properties.bootstrap.servers=servicekafka:9092 + +# JPA +logging.level.org.hibernate.SQL=debug +spring.jpa.properties.hibernate.enable_lazy_load_no_trans=true +spring.jpa.hibernate.ddl-auto=create + +# MySQL +spring.datasource.url=jdbc:mysql://${BD_PAY_CLUSTERIP_SERVICE_SERVICE_HOST}:${BD_PAY_CLUSTERIP_SERVICE_SERVICE_PORT}/db_operation?serverTimezone=America/Lima&allowPublicKeyRetrieval=true&useSSL=false +#spring.datasource.url=jdbc:mysql://mysql:3306/db_operation?serverTimezone=America/Lima&allowPublicKeyRetrieval=true&useSSL=false +spring.datasource.username=root +spring.datasource.password=MYSQL +spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver +spring.jpa.database-platform=org.hibernate.dialect.MySQL8Dialect \ No newline at end of file diff --git a/pay-app-spring-microservices/config/app-transaction-dev.properties b/pay-app-spring-microservices/config/app-transaction-dev.properties new file mode 100644 index 0000000..17d29f4 --- /dev/null +++ b/pay-app-spring-microservices/config/app-transaction-dev.properties @@ -0,0 +1,16 @@ +# Server +spring.application.name=app-transaction +server.port=8082 + +# Kafka +spring.kafka.consumer.bootstrap-servers=servicekafka:9092 +#spring.kafka.consumer.bootstrap-servers=servicekafka:9092 +spring.kafka.admin.properties.bootstrap.servers=servicekafka:9092 +#spring.kafka.admin.properties.bootstrap.servers=servicekafka:9092 +spring.kafka.consumer.key-deserializer=org.apache.kafka.common.serialization.IntegerDeserializer +spring.kafka.consumer.value-deserializer=org.apache.kafka.common.serialization.StringDeserializer +spring.kafka.consumer.group-id=transaction-events-listener-group + +# MongoDB +spring.data.mongodb.uri=mongodb://mongodb:27017/db_transaction +#spring.data.mongodb.uri=mongodb://mongodb:27017/db_transaction \ No newline at end of file diff --git a/pay-app-spring-microservices/haproxy/Dockerfile b/pay-app-spring-microservices/haproxy/Dockerfile new file mode 100644 index 0000000..9e9a3ad --- /dev/null +++ b/pay-app-spring-microservices/haproxy/Dockerfile @@ -0,0 +1,2 @@ +FROM haproxy:2.3 +COPY haproxy.cfg /usr/local/etc/haproxy/haproxy.cfg \ No newline at end of file diff --git a/pay-app-spring-microservices/haproxy/haproxy.cfg b/pay-app-spring-microservices/haproxy/haproxy.cfg new file mode 100644 index 0000000..3b54b0c --- /dev/null +++ b/pay-app-spring-microservices/haproxy/haproxy.cfg @@ -0,0 +1,34 @@ +defaults + timeout connect 5s + timeout client 1m + timeout server 1m + +frontend stats + bind *:1936 + mode http + stats uri / + stats show-legends + no log + +frontend http_front + bind *:80 + mode http + acl url_config path_beg /config + use_backend config_back if url_config + + default_backend http_back + +backend config_back + mode http + balance roundrobin + http-request set-path "%[path,regsub(^/config/,/)]" + server appconfig app-config.service.consul:8888 resolvers consul resolve-prefer ipv4 check +backend http_back + mode http + balance roundrobin + server-template mywebapp 1-10 _web._tcp.service.consul resolvers consul resolve-prefer ipv4 check + +resolvers consul + nameserver consul consul:8600 + accepted_payload_size 8192 + hold valid 5s diff --git a/pay-app-spring-microservices/resources/DB.md b/pay-app-spring-microservices/resources/DB.md new file mode 100644 index 0000000..231dbb3 --- /dev/null +++ b/pay-app-spring-microservices/resources/DB.md @@ -0,0 +1,54 @@ +# Endpoints + +A continuacion se detallan los scripts para la creación de las bases de datos respectivas para los microservicios + + +## PostgreSQL + +1. Levantar docker de PostgreSQL (Al levantar el docker automaticamente se incluye la base de datos a crear) +``` +$ docker run -p 5434:5432 --name postgres --network aforo255-test -e POSTGRES_PASSWORD=postgres -e POSTGRES_DB=db_invoice -d postgres:12-alpine +``` + +2. Si se desea agregar nueva base de datos se debe ingresar al docker de Postgres y crear la base: +``` +$ docker exec -it postgres bash +$ psql -U postgres +$ CREATE TABLE db_invoice; +``` + +3. Conectarse a la base de datos desde cualquier cliente SQL (Ejemplo: Dbeaver) y ejecutar el script: +``` +CREATE TABLE IF NOT EXISTS invoice +( + id_invoice integer not null, + amount numeric, + state integer, + primary key (id_invoice) +); +``` + +## MySQL + +1. Levantar docker de MySQL (Al levantar el docker automaticamente se incluye la base de datos a crear) +``` +$ docker run -p 3307:3306 --name microservicio-mysql8 --network aforo255-test -e MYSQL_ROOT_PASSWORD=mysql -e MYSQL_DATABASE=db_operation -d mysql:8 +``` + +2. Conectarse a la base de datos desde cualquier cliente SQL (Ejemplo: Dbeaver) y ejecutar el script: +``` +CREATE TABLE pay +( + id_invoice integer not null, + amount numeric, + state integer, + primary key (id_invoice) +); +``` + +## MongoDB + +1. Levantar docker de MongoDB (Al levantar el microservicio y almacenar un registro se crea automaticamente la coleccion en mongo) +``` +$ docker run -p 27018:27017 --network aforo255-test --name mongodb -d mongo +``` \ No newline at end of file diff --git a/pay-app-spring-microservices/resources/INFO.md b/pay-app-spring-microservices/resources/INFO.md new file mode 100644 index 0000000..7bfc0c1 --- /dev/null +++ b/pay-app-spring-microservices/resources/INFO.md @@ -0,0 +1,63 @@ +# Endpoints + +A continuacion se detallan los endpoints y se adjuntan los Curl respectivos de cada microservicio para cumplir con las funcionalidad del trabajo + + +## Microservicios + +#### app-config + +Microservicio que se encarga de manejar las configuraciones de los microservicios, las configuraciones están en el siguiente directorio: + +[Configuraciones](https://github.com/icesi-ops/training_microservices.git) + +Endpoints para consultar configuraciones de los microservicios: + +* Curl consultar las configuraciones de los microservicios almacenadas en el repositorio +``` +curl --location --request GET 'http://localhost:8888/app-pay/dev' + +curl --location --request GET 'http://localhost:8888/app-invoice/dev' + +curl --location --request GET 'http://localhost:8888/app-transaction/dev' +``` + +#### app-pay + +Microservicio que se encarga de registrar los pagos de una factura + +[Dockerfile](https://github.com/icesi-ops/training_microservices.git) + +* Curl del servicio para registrar pagos +``` +curl --location --request POST 'http://localhost:8010/pay' \ +--header 'Content-Type: application/json' \ +--data-raw '{ + "idOperation": 1, + "idInvoice": 1, + "amount": 900, + "dateTime": "2021-05-21" +}' +``` + +#### app-inovice + +Microservicio que se encarga de obtener los mensajes de kafka y actualizar el estado de una factura segun el pago registrado + +[Dockerfile](https://github.com/icesi-ops/training_microservices.git) + +* Curl del servicio para obtener el detalle de todos los invoices +``` +curl --location --request GET 'http://localhost:8006/all' +``` + +#### app-transaction + +Microservicio que se encarga de obtener los mensajes de kafka y registrar las transacciones que se realizan con el pago de las facturas + +[Dockerfile](https://github.com/icesi-ops/training_microservices.git) + +* Curl del servicio para obtener el detalle de todos los invoices +``` +curl --location --request GET 'http://localhost:8082/all' +``` diff --git a/pay-app-spring-microservices/resources/microservicesarchitecture.png b/pay-app-spring-microservices/resources/microservicesarchitecture.png new file mode 100644 index 0000000..c10185b Binary files /dev/null and b/pay-app-spring-microservices/resources/microservicesarchitecture.png differ diff --git a/pay-app-spring-microservices/resources/mysql/Dockerfile b/pay-app-spring-microservices/resources/mysql/Dockerfile new file mode 100644 index 0000000..32bc267 --- /dev/null +++ b/pay-app-spring-microservices/resources/mysql/Dockerfile @@ -0,0 +1,6 @@ +FROM mysql:8 + +env MYSQL_ROOT_PASSWORD=MYSQL +env MYSQL_DATABASE=db_operation +COPY ./mysql.sql /docker-entrypoint-initdb.d + diff --git a/pay-app-spring-microservices/resources/mysql/mysql.sql b/pay-app-spring-microservices/resources/mysql/mysql.sql new file mode 100644 index 0000000..37a094a --- /dev/null +++ b/pay-app-spring-microservices/resources/mysql/mysql.sql @@ -0,0 +1,6 @@ +CREATE TABLE pay ( + id_invoice integer not null, + amount numeric, + state integer, + primary key (id_invoice) +); \ No newline at end of file diff --git a/pay-app-spring-microservices/resources/postgres/Dockerfile b/pay-app-spring-microservices/resources/postgres/Dockerfile new file mode 100644 index 0000000..450d83f --- /dev/null +++ b/pay-app-spring-microservices/resources/postgres/Dockerfile @@ -0,0 +1,6 @@ +FROM postgres:12-alpine + +env POSTGRES_PASSWORD=postgres +env POSTGRES_DB=db_invoice +COPY ./postgres.sql /docker-entrypoint-initdb.d + diff --git a/pay-app-spring-microservices/resources/postgres/data.sql b/pay-app-spring-microservices/resources/postgres/data.sql new file mode 100644 index 0000000..dac1339 --- /dev/null +++ b/pay-app-spring-microservices/resources/postgres/data.sql @@ -0,0 +1,5 @@ +INSERT INTO invoice(id_invoice, amount, state) VALUES(1, 1000, 0); +INSERT INTO invoice(id_invoice, amount, state) VALUES(2, 5000, 1); +INSERT INTO invoice(id_invoice, amount, state) VALUES(3, 300, 0); +INSERT INTO invoice(id_invoice, amount, state) VALUES(4, 600, 0); +INSERT INTO invoice(id_invoice, amount, state) VALUES(5, 400, 0); \ No newline at end of file diff --git a/pay-app-spring-microservices/resources/postgres/postgres.sql b/pay-app-spring-microservices/resources/postgres/postgres.sql new file mode 100644 index 0000000..3ffced7 --- /dev/null +++ b/pay-app-spring-microservices/resources/postgres/postgres.sql @@ -0,0 +1,5 @@ +CREATE TABLE IF NOT EXISTS invoice ( + id_invoice integer GENERATED by default as IDENTITY PRIMARY KEY, + amount numeric, + state integer +)