diff --git a/.drone.yml b/.drone.yml new file mode 100644 index 0000000..9dbcb5c --- /dev/null +++ b/.drone.yml @@ -0,0 +1,89 @@ +kind: pipeline +type: docker +name: spring-boot-java21 + +workspace: + base: /drone/src + +steps: + # Paso 1: Build y tests con Maven (Java 21) + - name: build-and-test + image: maven:3.9-eclipse-temurin-21-alpine + environment: + MAVEN_OPTS: -Xmx2048m -XX:+TieredCompilation -XX:TieredStopAtLevel=1 + commands: + - mvn clean verify --settings nexus-settings.xml + - mvn jacoco:report # Generar reporte de cobertura + volumes: + - name: maven-cache + path: /root/.m2 + + # # Paso 2: Análisis SonarQube con Maven + - name: sonarqube-analysis + image: maven:3.9-eclipse-temurin-21-alpine + environment: + #SONAR_HOST_URL: ${SONARQUBE_URL} # URL de tu servidor SonarQube + #SONAR_LOGIN: ${SONARQUBE_TOKEN} # Token de autenticación en SonarQube + #SONAR_PROJECT_KEY: ${SONARQUBE_PROJECT_KEY} # Clave del proyecto en SonarQube + SONAR_HOST_URL: http://10.0.0.126:9000 # URL de tu servidor SonarQube + SONAR_LOGIN: squ_465ae384ffda803d8e58d9ef0111bef1277c874a # Token de autenticación en SonarQube + SONAR_PROJECT_KEY: hhh # Clave del proyecto en SonarQube + commands: + #- mvn sonar:sonar # Ejecuta el análisis de SonarQube usando Maven + - mvn clean verify sonar:sonar -DskipTests --settings nexus-settings.xml + when: + event: [push, pull_request] + + # Paso 3: Build y Push de Docker Image a Nexus (NUEVO) + - name: docker-build-push + image: docker:20.10.24 + environment: + NEXUS_USER: yandel # Usuario de Nexus con permisos push + NEXUS_PASSWORD: yandel # Contraseña del usuario + REGISTRY_ADDRESS: 10.0.0.126:8085 + REPOSITORY_NAME: docker-repository # Nombre del repositorio Docker en Nexus + commands: + # Login a Nexus Docker Registry + - docker login -u $NEXUS_USER -p $NEXUS_PASSWORD $REGISTRY_ADDRESS + + # Construir imagen con tag dinámico + - docker build -t $REGISTRY_ADDRESS/$REPOSITORY_NAME/${DRONE_REPO_NAME}:${DRONE_COMMIT_SHA} -f src/main/docker/dockerfile . # -f para especificar ruta + + # Push de la imagen + - docker push $REGISTRY_ADDRESS/$REPOSITORY_NAME/${DRONE_REPO_NAME}:${DRONE_COMMIT_SHA} + volumes: + - name: docker-sock + path: /var/run/docker.sock + + # Paso 4: Despliegue en Servidor Externo + # - name: deploy-to-server + # image: appleboy/drone-ssh + # environment: + # REGISTRY_ADDRESS: 10.0.0.126:8085 + # REPOSITORY_NAME: docker-repository # Nombre del repositorio Docker en Nexus + # settings: + # host: + # - 10.0.0.117 + # - 10.0.0.116 + # username: + # from_secret: ssh_usuario_117 + # password: + # from_secret: ssh_password_117 + # port: 22 + # command_timeout: 2m + # script: + # - echo "Iniciando despliegue..." + # - docker login -u yandel -p ${REGISTRY_ADDRESS} + # - docker stop mi-app || true + # - docker rm mi-app || true + # - docker pull 10.0.0.126:8085/docker-repository/${DRONE_REPO_NAME}:${DRONE_COMMIT_SHA} + # - docker run -d --name mi-app -p 8082:8080 10.0.0.126:8085/docker-repository/${DRONE_REPO_NAME}:${DRONE_COMMIT_SHA} + # #- docker pull $NEXUS_PASSWORD $REGISTRY_ADDRESS/docker-repository/${DRONE_REPO_NAME}:${DRONE_COMMIT_SHA} + # #- docker run -d --name mi-app -p 8082:8080 $NEXUS_PASSWORD $REGISTRY_ADDRESS/docker-repository/${DRONE_REPO_NAME}:${DRONE_COMMIT_SHA} + # - echo "Fin despliegue..." +volumes: + - name: maven-cache + temp: {} + - name: docker-sock + host: + path: /var/run/docker.sock # Montar socket de Docker diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..3b41682 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +/mvnw text eol=lf +*.cmd text eol=crlf diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..549e00a --- /dev/null +++ b/.gitignore @@ -0,0 +1,33 @@ +HELP.md +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 0000000..d58dfb7 --- /dev/null +++ b/.mvn/wrapper/maven-wrapper.properties @@ -0,0 +1,19 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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 +# +# http://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. +wrapperVersion=3.3.2 +distributionType=only-script +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.9/apache-maven-3.9.9-bin.zip diff --git a/mvnw b/mvnw new file mode 100644 index 0000000..19529dd --- /dev/null +++ b/mvnw @@ -0,0 +1,259 @@ +#!/bin/sh +# ---------------------------------------------------------------------------- +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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 +# +# http://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. +# ---------------------------------------------------------------------------- + +# ---------------------------------------------------------------------------- +# Apache Maven Wrapper startup batch script, version 3.3.2 +# +# Optional ENV vars +# ----------------- +# JAVA_HOME - location of a JDK home dir, required when download maven via java source +# MVNW_REPOURL - repo url base for downloading maven distribution +# MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven +# MVNW_VERBOSE - true: enable verbose log; debug: trace the mvnw script; others: silence the output +# ---------------------------------------------------------------------------- + +set -euf +[ "${MVNW_VERBOSE-}" != debug ] || set -x + +# OS specific support. +native_path() { printf %s\\n "$1"; } +case "$(uname)" in +CYGWIN* | MINGW*) + [ -z "${JAVA_HOME-}" ] || JAVA_HOME="$(cygpath --unix "$JAVA_HOME")" + native_path() { cygpath --path --windows "$1"; } + ;; +esac + +# set JAVACMD and JAVACCMD +set_java_home() { + # For Cygwin and MinGW, ensure paths are in Unix format before anything is touched + 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" + JAVACCMD="$JAVA_HOME/jre/sh/javac" + else + JAVACMD="$JAVA_HOME/bin/java" + JAVACCMD="$JAVA_HOME/bin/javac" + + if [ ! -x "$JAVACMD" ] || [ ! -x "$JAVACCMD" ]; then + echo "The JAVA_HOME environment variable is not defined correctly, so mvnw cannot run." >&2 + echo "JAVA_HOME is set to \"$JAVA_HOME\", but \"\$JAVA_HOME/bin/java\" or \"\$JAVA_HOME/bin/javac\" does not exist." >&2 + return 1 + fi + fi + else + JAVACMD="$( + 'set' +e + 'unset' -f command 2>/dev/null + 'command' -v java + )" || : + JAVACCMD="$( + 'set' +e + 'unset' -f command 2>/dev/null + 'command' -v javac + )" || : + + if [ ! -x "${JAVACMD-}" ] || [ ! -x "${JAVACCMD-}" ]; then + echo "The java/javac command does not exist in PATH nor is JAVA_HOME set, so mvnw cannot run." >&2 + return 1 + fi + fi +} + +# hash string like Java String::hashCode +hash_string() { + str="${1:-}" h=0 + while [ -n "$str" ]; do + char="${str%"${str#?}"}" + h=$(((h * 31 + $(LC_CTYPE=C printf %d "'$char")) % 4294967296)) + str="${str#?}" + done + printf %x\\n $h +} + +verbose() { :; } +[ "${MVNW_VERBOSE-}" != true ] || verbose() { printf %s\\n "${1-}"; } + +die() { + printf %s\\n "$1" >&2 + exit 1 +} + +trim() { + # MWRAPPER-139: + # Trims trailing and leading whitespace, carriage returns, tabs, and linefeeds. + # Needed for removing poorly interpreted newline sequences when running in more + # exotic environments such as mingw bash on Windows. + printf "%s" "${1}" | tr -d '[:space:]' +} + +# parse distributionUrl and optional distributionSha256Sum, requires .mvn/wrapper/maven-wrapper.properties +while IFS="=" read -r key value; do + case "${key-}" in + distributionUrl) distributionUrl=$(trim "${value-}") ;; + distributionSha256Sum) distributionSha256Sum=$(trim "${value-}") ;; + esac +done <"${0%/*}/.mvn/wrapper/maven-wrapper.properties" +[ -n "${distributionUrl-}" ] || die "cannot read distributionUrl property in ${0%/*}/.mvn/wrapper/maven-wrapper.properties" + +case "${distributionUrl##*/}" in +maven-mvnd-*bin.*) + MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ + case "${PROCESSOR_ARCHITECTURE-}${PROCESSOR_ARCHITEW6432-}:$(uname -a)" in + *AMD64:CYGWIN* | *AMD64:MINGW*) distributionPlatform=windows-amd64 ;; + :Darwin*x86_64) distributionPlatform=darwin-amd64 ;; + :Darwin*arm64) distributionPlatform=darwin-aarch64 ;; + :Linux*x86_64*) distributionPlatform=linux-amd64 ;; + *) + echo "Cannot detect native platform for mvnd on $(uname)-$(uname -m), use pure java version" >&2 + distributionPlatform=linux-amd64 + ;; + esac + distributionUrl="${distributionUrl%-bin.*}-$distributionPlatform.zip" + ;; +maven-mvnd-*) MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ ;; +*) MVN_CMD="mvn${0##*/mvnw}" _MVNW_REPO_PATTERN=/org/apache/maven/ ;; +esac + +# apply MVNW_REPOURL and calculate MAVEN_HOME +# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/ +[ -z "${MVNW_REPOURL-}" ] || distributionUrl="$MVNW_REPOURL$_MVNW_REPO_PATTERN${distributionUrl#*"$_MVNW_REPO_PATTERN"}" +distributionUrlName="${distributionUrl##*/}" +distributionUrlNameMain="${distributionUrlName%.*}" +distributionUrlNameMain="${distributionUrlNameMain%-bin}" +MAVEN_USER_HOME="${MAVEN_USER_HOME:-${HOME}/.m2}" +MAVEN_HOME="${MAVEN_USER_HOME}/wrapper/dists/${distributionUrlNameMain-}/$(hash_string "$distributionUrl")" + +exec_maven() { + unset MVNW_VERBOSE MVNW_USERNAME MVNW_PASSWORD MVNW_REPOURL || : + exec "$MAVEN_HOME/bin/$MVN_CMD" "$@" || die "cannot exec $MAVEN_HOME/bin/$MVN_CMD" +} + +if [ -d "$MAVEN_HOME" ]; then + verbose "found existing MAVEN_HOME at $MAVEN_HOME" + exec_maven "$@" +fi + +case "${distributionUrl-}" in +*?-bin.zip | *?maven-mvnd-?*-?*.zip) ;; +*) die "distributionUrl is not valid, must match *-bin.zip or maven-mvnd-*.zip, but found '${distributionUrl-}'" ;; +esac + +# prepare tmp dir +if TMP_DOWNLOAD_DIR="$(mktemp -d)" && [ -d "$TMP_DOWNLOAD_DIR" ]; then + clean() { rm -rf -- "$TMP_DOWNLOAD_DIR"; } + trap clean HUP INT TERM EXIT +else + die "cannot create temp dir" +fi + +mkdir -p -- "${MAVEN_HOME%/*}" + +# Download and Install Apache Maven +verbose "Couldn't find MAVEN_HOME, downloading and installing it ..." +verbose "Downloading from: $distributionUrl" +verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName" + +# select .zip or .tar.gz +if ! command -v unzip >/dev/null; then + distributionUrl="${distributionUrl%.zip}.tar.gz" + distributionUrlName="${distributionUrl##*/}" +fi + +# verbose opt +__MVNW_QUIET_WGET=--quiet __MVNW_QUIET_CURL=--silent __MVNW_QUIET_UNZIP=-q __MVNW_QUIET_TAR='' +[ "${MVNW_VERBOSE-}" != true ] || __MVNW_QUIET_WGET='' __MVNW_QUIET_CURL='' __MVNW_QUIET_UNZIP='' __MVNW_QUIET_TAR=v + +# normalize http auth +case "${MVNW_PASSWORD:+has-password}" in +'') MVNW_USERNAME='' MVNW_PASSWORD='' ;; +has-password) [ -n "${MVNW_USERNAME-}" ] || MVNW_USERNAME='' MVNW_PASSWORD='' ;; +esac + +if [ -z "${MVNW_USERNAME-}" ] && command -v wget >/dev/null; then + verbose "Found wget ... using wget" + wget ${__MVNW_QUIET_WGET:+"$__MVNW_QUIET_WGET"} "$distributionUrl" -O "$TMP_DOWNLOAD_DIR/$distributionUrlName" || die "wget: Failed to fetch $distributionUrl" +elif [ -z "${MVNW_USERNAME-}" ] && command -v curl >/dev/null; then + verbose "Found curl ... using curl" + curl ${__MVNW_QUIET_CURL:+"$__MVNW_QUIET_CURL"} -f -L -o "$TMP_DOWNLOAD_DIR/$distributionUrlName" "$distributionUrl" || die "curl: Failed to fetch $distributionUrl" +elif set_java_home; then + verbose "Falling back to use Java to download" + javaSource="$TMP_DOWNLOAD_DIR/Downloader.java" + targetZip="$TMP_DOWNLOAD_DIR/$distributionUrlName" + cat >"$javaSource" <<-END + public class Downloader extends java.net.Authenticator + { + protected java.net.PasswordAuthentication getPasswordAuthentication() + { + return new java.net.PasswordAuthentication( System.getenv( "MVNW_USERNAME" ), System.getenv( "MVNW_PASSWORD" ).toCharArray() ); + } + public static void main( String[] args ) throws Exception + { + setDefault( new Downloader() ); + java.nio.file.Files.copy( java.net.URI.create( args[0] ).toURL().openStream(), java.nio.file.Paths.get( args[1] ).toAbsolutePath().normalize() ); + } + } + END + # For Cygwin/MinGW, switch paths to Windows format before running javac and java + verbose " - Compiling Downloader.java ..." + "$(native_path "$JAVACCMD")" "$(native_path "$javaSource")" || die "Failed to compile Downloader.java" + verbose " - Running Downloader.java ..." + "$(native_path "$JAVACMD")" -cp "$(native_path "$TMP_DOWNLOAD_DIR")" Downloader "$distributionUrl" "$(native_path "$targetZip")" +fi + +# If specified, validate the SHA-256 sum of the Maven distribution zip file +if [ -n "${distributionSha256Sum-}" ]; then + distributionSha256Result=false + if [ "$MVN_CMD" = mvnd.sh ]; then + echo "Checksum validation is not supported for maven-mvnd." >&2 + echo "Please disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2 + exit 1 + elif command -v sha256sum >/dev/null; then + if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | sha256sum -c >/dev/null 2>&1; then + distributionSha256Result=true + fi + elif command -v shasum >/dev/null; then + if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | shasum -a 256 -c >/dev/null 2>&1; then + distributionSha256Result=true + fi + else + echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." >&2 + echo "Please install either command, or disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2 + exit 1 + fi + if [ $distributionSha256Result = false ]; then + echo "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised." >&2 + echo "If you updated your Maven version, you need to update the specified distributionSha256Sum property." >&2 + exit 1 + fi +fi + +# unzip and move +if command -v unzip >/dev/null; then + unzip ${__MVNW_QUIET_UNZIP:+"$__MVNW_QUIET_UNZIP"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -d "$TMP_DOWNLOAD_DIR" || die "failed to unzip" +else + tar xzf${__MVNW_QUIET_TAR:+"$__MVNW_QUIET_TAR"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -C "$TMP_DOWNLOAD_DIR" || die "failed to untar" +fi +printf %s\\n "$distributionUrl" >"$TMP_DOWNLOAD_DIR/$distributionUrlNameMain/mvnw.url" +mv -- "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" "$MAVEN_HOME" || [ -d "$MAVEN_HOME" ] || die "fail to move MAVEN_HOME" + +clean || : +exec_maven "$@" diff --git a/mvnw.cmd b/mvnw.cmd new file mode 100644 index 0000000..249bdf3 --- /dev/null +++ b/mvnw.cmd @@ -0,0 +1,149 @@ +<# : batch portion +@REM ---------------------------------------------------------------------------- +@REM Licensed to the Apache Software Foundation (ASF) under one +@REM or more contributor license agreements. See the NOTICE file +@REM distributed with this work for additional information +@REM regarding copyright ownership. The ASF licenses this file +@REM to you under the Apache License, Version 2.0 (the +@REM "License"); you may not use this file except in compliance +@REM with the License. You may obtain a copy of the License at +@REM +@REM http://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, +@REM software distributed under the License is distributed on an +@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +@REM KIND, either express or implied. See the License for the +@REM specific language governing permissions and limitations +@REM under the License. +@REM ---------------------------------------------------------------------------- + +@REM ---------------------------------------------------------------------------- +@REM Apache Maven Wrapper startup batch script, version 3.3.2 +@REM +@REM Optional ENV vars +@REM MVNW_REPOURL - repo url base for downloading maven distribution +@REM MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven +@REM MVNW_VERBOSE - true: enable verbose log; others: silence the output +@REM ---------------------------------------------------------------------------- + +@IF "%__MVNW_ARG0_NAME__%"=="" (SET __MVNW_ARG0_NAME__=%~nx0) +@SET __MVNW_CMD__= +@SET __MVNW_ERROR__= +@SET __MVNW_PSMODULEP_SAVE=%PSModulePath% +@SET PSModulePath= +@FOR /F "usebackq tokens=1* delims==" %%A IN (`powershell -noprofile "& {$scriptDir='%~dp0'; $script='%__MVNW_ARG0_NAME__%'; icm -ScriptBlock ([Scriptblock]::Create((Get-Content -Raw '%~f0'))) -NoNewScope}"`) DO @( + IF "%%A"=="MVN_CMD" (set __MVNW_CMD__=%%B) ELSE IF "%%B"=="" (echo %%A) ELSE (echo %%A=%%B) +) +@SET PSModulePath=%__MVNW_PSMODULEP_SAVE% +@SET __MVNW_PSMODULEP_SAVE= +@SET __MVNW_ARG0_NAME__= +@SET MVNW_USERNAME= +@SET MVNW_PASSWORD= +@IF NOT "%__MVNW_CMD__%"=="" (%__MVNW_CMD__% %*) +@echo Cannot start maven from wrapper >&2 && exit /b 1 +@GOTO :EOF +: end batch / begin powershell #> + +$ErrorActionPreference = "Stop" +if ($env:MVNW_VERBOSE -eq "true") { + $VerbosePreference = "Continue" +} + +# calculate distributionUrl, requires .mvn/wrapper/maven-wrapper.properties +$distributionUrl = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionUrl +if (!$distributionUrl) { + Write-Error "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties" +} + +switch -wildcard -casesensitive ( $($distributionUrl -replace '^.*/','') ) { + "maven-mvnd-*" { + $USE_MVND = $true + $distributionUrl = $distributionUrl -replace '-bin\.[^.]*$',"-windows-amd64.zip" + $MVN_CMD = "mvnd.cmd" + break + } + default { + $USE_MVND = $false + $MVN_CMD = $script -replace '^mvnw','mvn' + break + } +} + +# apply MVNW_REPOURL and calculate MAVEN_HOME +# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/ +if ($env:MVNW_REPOURL) { + $MVNW_REPO_PATTERN = if ($USE_MVND) { "/org/apache/maven/" } else { "/maven/mvnd/" } + $distributionUrl = "$env:MVNW_REPOURL$MVNW_REPO_PATTERN$($distributionUrl -replace '^.*'+$MVNW_REPO_PATTERN,'')" +} +$distributionUrlName = $distributionUrl -replace '^.*/','' +$distributionUrlNameMain = $distributionUrlName -replace '\.[^.]*$','' -replace '-bin$','' +$MAVEN_HOME_PARENT = "$HOME/.m2/wrapper/dists/$distributionUrlNameMain" +if ($env:MAVEN_USER_HOME) { + $MAVEN_HOME_PARENT = "$env:MAVEN_USER_HOME/wrapper/dists/$distributionUrlNameMain" +} +$MAVEN_HOME_NAME = ([System.Security.Cryptography.MD5]::Create().ComputeHash([byte[]][char[]]$distributionUrl) | ForEach-Object {$_.ToString("x2")}) -join '' +$MAVEN_HOME = "$MAVEN_HOME_PARENT/$MAVEN_HOME_NAME" + +if (Test-Path -Path "$MAVEN_HOME" -PathType Container) { + Write-Verbose "found existing MAVEN_HOME at $MAVEN_HOME" + Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD" + exit $? +} + +if (! $distributionUrlNameMain -or ($distributionUrlName -eq $distributionUrlNameMain)) { + Write-Error "distributionUrl is not valid, must end with *-bin.zip, but found $distributionUrl" +} + +# prepare tmp dir +$TMP_DOWNLOAD_DIR_HOLDER = New-TemporaryFile +$TMP_DOWNLOAD_DIR = New-Item -Itemtype Directory -Path "$TMP_DOWNLOAD_DIR_HOLDER.dir" +$TMP_DOWNLOAD_DIR_HOLDER.Delete() | Out-Null +trap { + if ($TMP_DOWNLOAD_DIR.Exists) { + try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null } + catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" } + } +} + +New-Item -Itemtype Directory -Path "$MAVEN_HOME_PARENT" -Force | Out-Null + +# Download and Install Apache Maven +Write-Verbose "Couldn't find MAVEN_HOME, downloading and installing it ..." +Write-Verbose "Downloading from: $distributionUrl" +Write-Verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName" + +$webclient = New-Object System.Net.WebClient +if ($env:MVNW_USERNAME -and $env:MVNW_PASSWORD) { + $webclient.Credentials = New-Object System.Net.NetworkCredential($env:MVNW_USERNAME, $env:MVNW_PASSWORD) +} +[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 +$webclient.DownloadFile($distributionUrl, "$TMP_DOWNLOAD_DIR/$distributionUrlName") | Out-Null + +# If specified, validate the SHA-256 sum of the Maven distribution zip file +$distributionSha256Sum = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionSha256Sum +if ($distributionSha256Sum) { + if ($USE_MVND) { + Write-Error "Checksum validation is not supported for maven-mvnd. `nPlease disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." + } + Import-Module $PSHOME\Modules\Microsoft.PowerShell.Utility -Function Get-FileHash + if ((Get-FileHash "$TMP_DOWNLOAD_DIR/$distributionUrlName" -Algorithm SHA256).Hash.ToLower() -ne $distributionSha256Sum) { + Write-Error "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised. If you updated your Maven version, you need to update the specified distributionSha256Sum property." + } +} + +# unzip and move +Expand-Archive "$TMP_DOWNLOAD_DIR/$distributionUrlName" -DestinationPath "$TMP_DOWNLOAD_DIR" | Out-Null +Rename-Item -Path "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" -NewName $MAVEN_HOME_NAME | Out-Null +try { + Move-Item -Path "$TMP_DOWNLOAD_DIR/$MAVEN_HOME_NAME" -Destination $MAVEN_HOME_PARENT | Out-Null +} catch { + if (! (Test-Path -Path "$MAVEN_HOME" -PathType Container)) { + Write-Error "fail to move MAVEN_HOME" + } +} finally { + try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null } + catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" } +} + +Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD" diff --git a/nexus-settings.xml b/nexus-settings.xml new file mode 100644 index 0000000..1b6d68f --- /dev/null +++ b/nexus-settings.xml @@ -0,0 +1,35 @@ + + + + nexus + yandel + yandel + + + + + + org.sonarsource.scanner.maven + + + + + sonar + + true + + + http://10.0.0.126:9000 + squ_465ae384ffda803d8e58d9ef0111bef1277c874a + + + + + + sonar + + + \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..8afd1d4 --- /dev/null +++ b/pom.xml @@ -0,0 +1,101 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 3.4.4 + + + com.myapps + demoKafka + 0.0.1-SNAPSHOT + war + demoKafka + Demo project for Spring Boot + + + + + + + + + + + + + + + 17 + + + + + + + + + + + + + + + + + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-tomcat + provided + + + org.springframework.boot + spring-boot-starter-test + test + + + + org.springframework.kafka + spring-kafka + + + org.projectlombok + lombok + true + + + + org.springframework.boot + spring-boot-starter-mail + + + + + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + org.sonarsource.scanner.maven + sonar-maven-plugin + 3.10.0.2594 + + + + + diff --git a/sonar-project.properties b/sonar-project.properties new file mode 100644 index 0000000..bfe237e --- /dev/null +++ b/sonar-project.properties @@ -0,0 +1,22 @@ +sonar.projectKey=hhh +sonar.projectName=demoKafka + +sonar.sources=src/main/ +#sonar.host.url=http://192.168.1.90:9000 +#sonar.token=sqp_be04510fcd7f726558c210489203cc8cb9a3b799 + +sonar.tests=src/test/ + +sonar.exclusions=**/controller/core/**,**/graphql/** + +sonar.host.url=http://10.0.0.126:9000 +#sonar.host.url=http://sonarqube:9000 +#sonar.token=squ_095e01f2e60e4d77838a5a114356927fb1c99861 +sonar.login=squ_465ae384ffda803d8e58d9ef0111bef1277c874a +#sonar.login=sqp_249804bd04cbc7f86f7441a227ed7408b6b584ca +#sonar.login=channel +#sonar.password=Arroyo2024* + +#mvn clean verify sonar:sonar -DskipTests + + diff --git a/src/main/java/com/myapps/kafka/DemoKafkaApplication.java b/src/main/java/com/myapps/kafka/DemoKafkaApplication.java new file mode 100644 index 0000000..f97c865 --- /dev/null +++ b/src/main/java/com/myapps/kafka/DemoKafkaApplication.java @@ -0,0 +1,14 @@ +package com.myapps.kafka; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +//@SpringBootApplication +@SpringBootApplication(scanBasePackages = "com.myapps") +public class DemoKafkaApplication { + + public static void main(String[] args) { + SpringApplication.run(DemoKafkaApplication.class, args); + } + +} diff --git a/src/main/java/com/myapps/kafka/ServletInitializer.java b/src/main/java/com/myapps/kafka/ServletInitializer.java new file mode 100644 index 0000000..455ab9a --- /dev/null +++ b/src/main/java/com/myapps/kafka/ServletInitializer.java @@ -0,0 +1,13 @@ +package com.myapps.kafka; + +import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; + +public class ServletInitializer extends SpringBootServletInitializer { + + @Override + protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { + return application.sources(DemoKafkaApplication.class); + } + +} diff --git a/src/main/java/com/myapps/kafka/TestController.java b/src/main/java/com/myapps/kafka/TestController.java new file mode 100644 index 0000000..8728ba6 --- /dev/null +++ b/src/main/java/com/myapps/kafka/TestController.java @@ -0,0 +1,31 @@ +package com.myapps.kafka; + +import com.myapps.kafka.email.EmailService; +import com.myapps.kafka.producer.KafkaProducerService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.mail.SimpleMailMessage; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class TestController { + + @Autowired + private KafkaProducerService producerService; + + @Autowired + private EmailService emailService; + + @PostMapping("/send") + public String sendMessage(@RequestBody String message) { + producerService.sendMessage(message); + return "Mensaje enviado: " + message; + } + + + @PostMapping("/send/email") + public String sendMessageEmail(@RequestBody SimpleMailMessage simpleMailMessage) { + return emailService.sendAlertEmailApi(simpleMailMessage); + } +} diff --git a/src/main/java/com/myapps/kafka/consumer/KafkaConfig.java b/src/main/java/com/myapps/kafka/consumer/KafkaConfig.java new file mode 100644 index 0000000..b548bc6 --- /dev/null +++ b/src/main/java/com/myapps/kafka/consumer/KafkaConfig.java @@ -0,0 +1,33 @@ +package com.myapps.kafka.consumer; + +import org.apache.kafka.clients.consumer.ConsumerConfig; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.kafka.config.ConcurrentKafkaListenerContainerFactory; +import org.springframework.kafka.core.ConsumerFactory; +import org.springframework.kafka.core.DefaultKafkaConsumerFactory; + +import java.util.HashMap; +import java.util.Map; + +@Configuration +public class KafkaConfig { + + @Bean + public ConsumerFactory consumerFactory() { + Map props = new HashMap<>(); + props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, "10.0.0.128:9092"); + props.put(ConsumerConfig.GROUP_ID_CONFIG, "fraude-consumer-group3" + System.currentTimeMillis()); + props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringDeserializer"); + props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringDeserializer"); + props.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "earliest"); + return new DefaultKafkaConsumerFactory<>(props); + } + + @Bean + public ConcurrentKafkaListenerContainerFactory kafkaListenerContainerFactory() { + ConcurrentKafkaListenerContainerFactory factory = new ConcurrentKafkaListenerContainerFactory<>(); + factory.setConsumerFactory(consumerFactory()); + return factory; + } +} diff --git a/src/main/java/com/myapps/kafka/consumer/KafkaConsumerService.java b/src/main/java/com/myapps/kafka/consumer/KafkaConsumerService.java new file mode 100644 index 0000000..0891c5b --- /dev/null +++ b/src/main/java/com/myapps/kafka/consumer/KafkaConsumerService.java @@ -0,0 +1,183 @@ +package com.myapps.kafka.consumer; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.myapps.kafka.email.EmailService; +import com.myapps.kafka.model.dos.DebeziumEvent; +import com.myapps.kafka.model.tres.AuditData; +import com.myapps.kafka.model.tres.AuditEvent; +import com.myapps.kafka.model.uno.Transaccion; +import com.myapps.kafka.producer.KafkaProducerService; +import lombok.extern.slf4j.Slf4j; +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.Service; + +import java.util.Arrays; + +@Service +@Slf4j +public class KafkaConsumerService { + + private static final Logger log = LoggerFactory.getLogger(KafkaConsumerService.class); + + private static final int MAX_TRANSACCIONES = 10; + private static final double MONTO_MINIMO_ALERTA = 5000.0; + + + private static String[] listaTablas = {"PARAMETROS", "TRANSACCIONES", "USUARIOS"}; + private static String[] listaUsuarios = {"FRAUDE", "GGADMIN123"}; + private static String[] listaOperacionesNoPermitidas = {"DELETE", "UPDATE"}; + + + @Autowired + private KafkaProducerService producerService; + @Autowired + private EmailService emailService; + + @KafkaListener(topics = "parametros.GGADMIN123.MY_AUDIT_TRAIL") + public void listen(ConsumerRecord record) { + log.info("Mensaje Entrante"); + log.info("Mensaje recibido -> Key: {}, Value: {}", record.key(), record.value()); + // procesar(record.value()); + //alertar(record.value()); + auditoria(record.value()); + } + + private void auditoria(String value) { + try { + // Parseo del evento JSON + AuditEvent transaccion = mapearDos(value); + if (transaccion == null || transaccion.getAfter() == null) { + return; // Si no hay datos válidos, no procesar + } + + // Verificamos que el USERID sea "FRAUDE" + String userId = transaccion.getAfter().getUserId(); + String tabla = transaccion.getAfter().getObjName(); + if (Arrays.asList(listaTablas).contains(tabla) && !Arrays.asList(listaUsuarios).contains(userId)) { + // Evento que coincide con el usuario "FRAUDE" + + for (String operacion : listaOperacionesNoPermitidas) { + String sql = transaccion.getAfter().getSqlText(); + if (sql != null && sql.toUpperCase().contains(operacion)) { + String alertaJson = String.format( + "El usuario " + userId + " ejecuto una operacion no permitida en la tabla: " + tabla, + userId, + transaccion.getAfter().getSessionId(), + transaccion.getAfter().getEntryId(), + transaccion.getAfter().getnTimestampHash(), + transaccion.getAfter().getSqlBind(), + transaccion.getAfter().getSqlText() + ); + + log.warn("🚨 Alerta generada: {}", alertaJson); + } else { + log.info("La operación: {} es permitida ", operacion); + } + } + + } + + } catch (Exception e) { + log.error("Error procesando evento: {}", e.getMessage()); + log.error("Evento problemático: {}", value); + } + + } + + private void procesar(String value) { + Transaccion transaccion = mapear(value); + if (transaccion != null) { + log.info("Procesando: {}", value); + int transactionCount = 0; + double totalAmount = 0.0; + + // Actualizar contadores + transactionCount++; + totalAmount += transaccion.getAfter().getMonto(); + + // Aplicar reglas de negocio + boolean alerta = false; + String motivo = ""; + + if (transactionCount >= MAX_TRANSACCIONES) { + motivo = String.format("Número de transacciones excedido (%d >= %d)", + transactionCount, MAX_TRANSACCIONES); + alerta = true; + log.info("Se supero el numero de transacciones: {}", motivo); + } + + if (totalAmount >= MONTO_MINIMO_ALERTA) { + motivo += String.format("%sMonto acumulado superado (%.2f >= %.2f)", + motivo.isEmpty() ? "" : " | ", + totalAmount, MONTO_MINIMO_ALERTA); + alerta = true; + log.info("Se supero el monto maximo {}", motivo); + } + + if (alerta) { + // Construir mensaje de alerta + String alertaJson = String.format( + "{\"usuario_id\":%d,\"total_transacciones\":%d,\"monto_total\":%.2f,\"motivo\":\"%s\"}", + transaccion.getAfter().getUsuarioId(), transactionCount, totalAmount, motivo); + + log.info("🚨 Alerta generada: {}", alertaJson); + + producerService.sendMessage(alertaJson); + + + } + } + + } + + private Transaccion mapear(String value) { + if (value != null) { + ObjectMapper mapper = new ObjectMapper(); + try { + return mapper.readValue(value, Transaccion.class); + } catch (JsonProcessingException e) { + log.warn("Error al convertir el message: {}", value); + return null; + } + } + return null; + } + + private AuditEvent mapearDos(String value) { + if (value != null) { + ObjectMapper mapper = new ObjectMapper(); + try { + return mapper.readValue(value, AuditEvent.class); + } catch (JsonProcessingException e) { + log.warn("Error al convertir el message: {}", value); + return null; + } + } + return null; + } + + + public void alertar(String value) { + String subject = "Alerta: Debezium y Apache Flink"; + String body = value; + emailService.sendAlertEmail("miguel.claure@myapps.com.bo", subject, body); + } +/* + public static void main(String[] args) { + String json = "{\"before\":null,\"after\":{\"ID\":133265,\"USUARIO_ID\":7,\"MONTO\":77777,\"FECHA\":1743429643452990},\"source\":{\"version\":\"2.1.4.Final\",\"connector\":\"oracle\",\"name\":\"fraude\",\"ts_ms\":1743444043000,\"snapshot\":\"false\",\"db\":\"ORCLCDB\",\"sequence\":null,\"schema\":\"FRAUDE\",\"table\":\"TRANSACCIONES\",\"txId\":\"0a001400b0250200\",\"scn\":\"30883127\",\"commit_scn\":\"30883128\",\"lcr_position\":null,\"rs_id\":null,\"ssn\":0,\"redo_thread\":1,\"user_name\":\"FRAUDE\"},\"op\":\"c\",\"ts_ms\":1743444043795,\"transaction\":null}"; + try { + ObjectMapper mapper = new ObjectMapper(); + Transaccion transaccion= mapper.readValue(json, Transaccion.class); + System.out.println(transaccion.getAfter().getUsuarioId()); + } catch (JsonProcessingException e) { + System.err.println("ERROR: "+ e.getMessage()); + } + } + /* + */ +} diff --git a/src/main/java/com/myapps/kafka/email/EmailService.java b/src/main/java/com/myapps/kafka/email/EmailService.java new file mode 100644 index 0000000..fd716be --- /dev/null +++ b/src/main/java/com/myapps/kafka/email/EmailService.java @@ -0,0 +1,55 @@ +package com.myapps.kafka.email; + +import lombok.extern.slf4j.Slf4j; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.mail.MailException; +import org.springframework.mail.SimpleMailMessage; +import org.springframework.mail.javamail.JavaMailSender; +import org.springframework.stereotype.Service; + +@Service +@Slf4j +public class EmailService { + + private static final Logger log = LoggerFactory.getLogger(EmailService.class); + @Autowired + private JavaMailSender mailSender; + + public void sendAlertEmail(String to, String subject, String body) { + try { + log.info("Inicio envio de email: {}", body); + SimpleMailMessage message = new SimpleMailMessage(); + message.setTo(to); + message.setSubject(subject); + message.setText(body); + message.setFrom("tu_correo@outlook.com"); + + mailSender.send(message); + log.info("Finalizo envio de email: {}", body); + } catch (MailException mailException) { + log.error("MailException: {}", mailException.getMessage()); + } + } + + public String sendAlertEmailApi(SimpleMailMessage message) { + try { + mailSender.send(message); + log.info("Finalizo envio de email: {}", message.getText()); + return "OK"; + } catch (MailException mailException) { + log.error("MailException: {}", mailException.getMessage()); + return "FAIL"; + } + } + + public static void main(String[] args) { + EmailService emailService= new EmailService(); + emailService.sendAlertEmail("miguel.claure@myapps.com.bo","hola","hola"); + + } +} + + + diff --git a/src/main/java/com/myapps/kafka/model/dos/AuditTrail.java b/src/main/java/com/myapps/kafka/model/dos/AuditTrail.java new file mode 100644 index 0000000..1aa3644 --- /dev/null +++ b/src/main/java/com/myapps/kafka/model/dos/AuditTrail.java @@ -0,0 +1,275 @@ +package com.myapps.kafka.model.dos; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class AuditTrail { + @JsonProperty("SESSIONID") + private NumericField sessionId; + + @JsonProperty("ENTRYID") + private NumericField entryId; + + @JsonProperty("STATEMENT") + private NumericField statement; + + @JsonProperty("TIMESTAMP#") + private String timestamp; + + @JsonProperty("USERID") + private String userId; + + @JsonProperty("USERHOST") + private String userHost; + + @JsonProperty("TERMINAL") + private String terminal; + + @JsonProperty("ACTION#") + private NumericField action; + + @JsonProperty("RETURNCODE") + private NumericField returnCode; + + @JsonProperty("OBJ$CREATOR") + private String objectCreator; + + @JsonProperty("OBJ$NAME") + private String objectName; + + @JsonProperty("AUTH$PRIVILEGES") + private String authPrivileges; + + @JsonProperty("AUTH$GRANTEE") + private String authGrantee; + + @JsonProperty("SPARE1") + private String spare1; + + @JsonProperty("SQLBIND") + private String sqlBind; + + @JsonProperty("SQLTEXT") + private String sqlText; + + @JsonProperty("NTIMESTAMP#") + private Long nTimestamp; + + @JsonProperty("PROCESS#") + private String process; + + @JsonProperty("INSTANCE#") + private NumericField instance; + + @JsonProperty("SCN") + private NumericField scn; + + @JsonProperty("DBID") + private NumericField dbid; + + @JsonProperty("CURRENT_USER") + private String currentUser; + + public NumericField getSessionId() { + return sessionId; + } + + public void setSessionId(NumericField sessionId) { + this.sessionId = sessionId; + } + + public NumericField getEntryId() { + return entryId; + } + + public void setEntryId(NumericField entryId) { + this.entryId = entryId; + } + + public NumericField getStatement() { + return statement; + } + + public void setStatement(NumericField statement) { + this.statement = statement; + } + + public String getTimestamp() { + return timestamp; + } + + public void setTimestamp(String timestamp) { + this.timestamp = timestamp; + } + + public String getUserId() { + return userId; + } + + public void setUserId(String userId) { + this.userId = userId; + } + + public String getUserHost() { + return userHost; + } + + public void setUserHost(String userHost) { + this.userHost = userHost; + } + + public String getTerminal() { + return terminal; + } + + public void setTerminal(String terminal) { + this.terminal = terminal; + } + + public NumericField getAction() { + return action; + } + + public void setAction(NumericField action) { + this.action = action; + } + + public NumericField getReturnCode() { + return returnCode; + } + + public void setReturnCode(NumericField returnCode) { + this.returnCode = returnCode; + } + + public String getObjectCreator() { + return objectCreator; + } + + public void setObjectCreator(String objectCreator) { + this.objectCreator = objectCreator; + } + + public String getObjectName() { + return objectName; + } + + public void setObjectName(String objectName) { + this.objectName = objectName; + } + + public String getAuthPrivileges() { + return authPrivileges; + } + + public void setAuthPrivileges(String authPrivileges) { + this.authPrivileges = authPrivileges; + } + + public String getAuthGrantee() { + return authGrantee; + } + + public void setAuthGrantee(String authGrantee) { + this.authGrantee = authGrantee; + } + + public String getSpare1() { + return spare1; + } + + public void setSpare1(String spare1) { + this.spare1 = spare1; + } + + public String getSqlBind() { + return sqlBind; + } + + public void setSqlBind(String sqlBind) { + this.sqlBind = sqlBind; + } + + public String getSqlText() { + return sqlText; + } + + public void setSqlText(String sqlText) { + this.sqlText = sqlText; + } + + public Long getnTimestamp() { + return nTimestamp; + } + + public void setnTimestamp(Long nTimestamp) { + this.nTimestamp = nTimestamp; + } + + public String getProcess() { + return process; + } + + public void setProcess(String process) { + this.process = process; + } + + public NumericField getInstance() { + return instance; + } + + public void setInstance(NumericField instance) { + this.instance = instance; + } + + public NumericField getScn() { + return scn; + } + + public void setScn(NumericField scn) { + this.scn = scn; + } + + public NumericField getDbid() { + return dbid; + } + + public void setDbid(NumericField dbid) { + this.dbid = dbid; + } + + public String getCurrentUser() { + return currentUser; + } + + public void setCurrentUser(String currentUser) { + this.currentUser = currentUser; + } + + public AuditTrail() { + } + + public AuditTrail(NumericField sessionId, NumericField entryId, NumericField statement, String timestamp, String userId, String userHost, String terminal, NumericField action, NumericField returnCode, String objectCreator, String objectName, String authPrivileges, String authGrantee, String spare1, String sqlBind, String sqlText, Long nTimestamp, String process, NumericField instance, NumericField scn, NumericField dbid, String currentUser) { + this.sessionId = sessionId; + this.entryId = entryId; + this.statement = statement; + this.timestamp = timestamp; + this.userId = userId; + this.userHost = userHost; + this.terminal = terminal; + this.action = action; + this.returnCode = returnCode; + this.objectCreator = objectCreator; + this.objectName = objectName; + this.authPrivileges = authPrivileges; + this.authGrantee = authGrantee; + this.spare1 = spare1; + this.sqlBind = sqlBind; + this.sqlText = sqlText; + this.nTimestamp = nTimestamp; + this.process = process; + this.instance = instance; + this.scn = scn; + this.dbid = dbid; + this.currentUser = currentUser; + } +} diff --git a/src/main/java/com/myapps/kafka/model/dos/DebeziumEvent.java b/src/main/java/com/myapps/kafka/model/dos/DebeziumEvent.java new file mode 100644 index 0000000..83fb5a1 --- /dev/null +++ b/src/main/java/com/myapps/kafka/model/dos/DebeziumEvent.java @@ -0,0 +1,73 @@ +package com.myapps.kafka.model.dos; + + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class DebeziumEvent { + @JsonProperty("before") + private AuditTrail before; + + @JsonProperty("after") + private AuditTrail after; + + @JsonProperty("source") + private DebeziumSource source; + + @JsonProperty("op") + private String operation; + + @JsonProperty("ts_ms") + private Long timestamp; + + + public AuditTrail getBefore() { + return before; + } + + public void setBefore(AuditTrail before) { + this.before = before; + } + + public AuditTrail getAfter() { + return after; + } + + public void setAfter(AuditTrail after) { + this.after = after; + } + + public DebeziumSource getSource() { + return source; + } + + public void setSource(DebeziumSource source) { + this.source = source; + } + + public String getOperation() { + return operation; + } + + public void setOperation(String operation) { + this.operation = operation; + } + + public Long getTimestamp() { + return timestamp; + } + + public void setTimestamp(Long timestamp) { + this.timestamp = timestamp; + } + + public DebeziumEvent() { + } + + public DebeziumEvent(AuditTrail before, AuditTrail after, DebeziumSource source, String operation, Long timestamp) { + this.before = before; + this.after = after; + this.source = source; + this.operation = operation; + this.timestamp = timestamp; + } +} diff --git a/src/main/java/com/myapps/kafka/model/dos/DebeziumSource.java b/src/main/java/com/myapps/kafka/model/dos/DebeziumSource.java new file mode 100644 index 0000000..137695e --- /dev/null +++ b/src/main/java/com/myapps/kafka/model/dos/DebeziumSource.java @@ -0,0 +1,157 @@ +package com.myapps.kafka.model.dos; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class DebeziumSource { + @JsonProperty("version") + private String version; + + @JsonProperty("connector") + private String connector; + + @JsonProperty("name") + private String name; + + @JsonProperty("ts_ms") + private Long timestamp; + + @JsonProperty("snapshot") + private String snapshot; + + @JsonProperty("db") + private String database; + + @JsonProperty("schema") + private String schema; + + @JsonProperty("table") + private String table; + + @JsonProperty("txId") + private String transactionId; + + @JsonProperty("scn") + private String scn; + + @JsonProperty("commit_scn") + private String commitScn; + + @JsonProperty("user_name") + private String userName; + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + + public String getConnector() { + return connector; + } + + public void setConnector(String connector) { + this.connector = connector; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Long getTimestamp() { + return timestamp; + } + + public void setTimestamp(Long timestamp) { + this.timestamp = timestamp; + } + + public String getSnapshot() { + return snapshot; + } + + public void setSnapshot(String snapshot) { + this.snapshot = snapshot; + } + + public String getDatabase() { + return database; + } + + public void setDatabase(String database) { + this.database = database; + } + + public String getSchema() { + return schema; + } + + public void setSchema(String schema) { + this.schema = schema; + } + + public String getTable() { + return table; + } + + public void setTable(String table) { + this.table = table; + } + + public String getTransactionId() { + return transactionId; + } + + public void setTransactionId(String transactionId) { + this.transactionId = transactionId; + } + + public String getScn() { + return scn; + } + + public void setScn(String scn) { + this.scn = scn; + } + + public String getCommitScn() { + return commitScn; + } + + public void setCommitScn(String commitScn) { + this.commitScn = commitScn; + } + + public String getUserName() { + return userName; + } + + public void setUserName(String userName) { + this.userName = userName; + } + + + public DebeziumSource() { + } + + public DebeziumSource(String version, String connector, String name, Long timestamp, String snapshot, String database, String schema, String table, String transactionId, String scn, String commitScn, String userName) { + this.version = version; + this.connector = connector; + this.name = name; + this.timestamp = timestamp; + this.snapshot = snapshot; + this.database = database; + this.schema = schema; + this.table = table; + this.transactionId = transactionId; + this.scn = scn; + this.commitScn = commitScn; + this.userName = userName; + } +} + diff --git a/src/main/java/com/myapps/kafka/model/dos/NumericField.java b/src/main/java/com/myapps/kafka/model/dos/NumericField.java new file mode 100644 index 0000000..059df3d --- /dev/null +++ b/src/main/java/com/myapps/kafka/model/dos/NumericField.java @@ -0,0 +1,36 @@ +package com.myapps.kafka.model.dos; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class NumericField { + @JsonProperty("scale") + private int scale; + + @JsonProperty("value") + private String value; + + public int getScale() { + return scale; + } + + public void setScale(int scale) { + this.scale = scale; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + public NumericField() { + } + + public NumericField(int scale, String value) { + this.scale = scale; + this.value = value; + } +} + diff --git a/src/main/java/com/myapps/kafka/model/tres/AuditData.java b/src/main/java/com/myapps/kafka/model/tres/AuditData.java new file mode 100644 index 0000000..03ae76b --- /dev/null +++ b/src/main/java/com/myapps/kafka/model/tres/AuditData.java @@ -0,0 +1,541 @@ +package com.myapps.kafka.model.tres; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class AuditData { + @JsonProperty("SESSIONID") + public ScaleValue sessionId; + + @JsonProperty("ENTRYID") + public ScaleValue entryId; + + @JsonProperty("STATEMENT") + public ScaleValue statement; + + @JsonProperty("TIMESTAMP#") + public Object timestampHash; + + @JsonProperty("USERID") + public String userId; + + @JsonProperty("USERHOST") + public String userHost; + + @JsonProperty("TERMINAL") + public String terminal; + + @JsonProperty("ACTION#") + public ScaleValue actionHash; + + @JsonProperty("RETURNCODE") + public ScaleValue returnCode; + + @JsonProperty("OBJ$CREATOR") + public String objCreator; + + @JsonProperty("OBJ$NAME") + public String objName; + + // Resto de campos manteniendo el patrón + @JsonProperty("AUTH$PRIVILEGES") + public Object authPrivileges; + + @JsonProperty("AUTH$GRANTEE") + public Object authGrantee; + + @JsonProperty("NEW$OWNER") + public Object newOwner; + + @JsonProperty("NEW$NAME") + public Object newName; + + @JsonProperty("SES$ACTIONS") + public Object sesActions; + + @JsonProperty("SES$TID") + public Object sesTid; + + @JsonProperty("LOGOFF$LREAD") + public Object logoffLread; + + @JsonProperty("LOGOFF$PREAD") + public Object logoffPread; + + @JsonProperty("LOGOFF$LWRITE") + public Object logoffLwrite; + + @JsonProperty("LOGOFF$DEAD") + public Object logoffDead; + + @JsonProperty("LOGOFF$TIME") + public Object logoffTime; + + @JsonProperty("COMMENT$TEXT") + public Object commentText; + + @JsonProperty("CLIENTID") + public Object clientId; + + @JsonProperty("SPARE1") + public String spare1; + + @JsonProperty("SPARE2") + public Object spare2; + + @JsonProperty("OBJ$LABEL") + public Object objLabel; + + @JsonProperty("SES$LABEL") + public Object sesLabel; + + @JsonProperty("PRIV$USED") + public Object privUsed; + + @JsonProperty("SESSIONCPU") + public Object sessionCpu; + + @JsonProperty("NTIMESTAMP#") + public Long nTimestampHash; + + @JsonProperty("PROXY$SID") + public Object proxySid; + + @JsonProperty("USER$GUID") + public Object userGuid; + + @JsonProperty("INSTANCE#") + public ScaleValue instanceHash; + + @JsonProperty("PROCESS#") + public String processHash; + + @JsonProperty("XID") + public String xid; + + @JsonProperty("AUDITID") + public Object auditId; + + @JsonProperty("SCN") + public ScaleValue scn; + + @JsonProperty("DBID") + public ScaleValue dbId; + + @JsonProperty("SQLBIND") + public String sqlBind; + + @JsonProperty("SQLTEXT") + public String sqlText; + + @JsonProperty("OBJ$EDITION") + public Object objEdition; + + @JsonProperty("RLS$INFO") + public Object rlsInfo; + + @JsonProperty("CURRENT_USER") + public String currentUser; + + + public ScaleValue getSessionId() { + return sessionId; + } + + public void setSessionId(ScaleValue sessionId) { + this.sessionId = sessionId; + } + + public ScaleValue getEntryId() { + return entryId; + } + + public void setEntryId(ScaleValue entryId) { + this.entryId = entryId; + } + + public ScaleValue getStatement() { + return statement; + } + + public void setStatement(ScaleValue statement) { + this.statement = statement; + } + + public Object getTimestampHash() { + return timestampHash; + } + + public void setTimestampHash(Object timestampHash) { + this.timestampHash = timestampHash; + } + + public String getUserId() { + return userId; + } + + public void setUserId(String userId) { + this.userId = userId; + } + + public String getUserHost() { + return userHost; + } + + public void setUserHost(String userHost) { + this.userHost = userHost; + } + + public String getTerminal() { + return terminal; + } + + public void setTerminal(String terminal) { + this.terminal = terminal; + } + + public ScaleValue getActionHash() { + return actionHash; + } + + public void setActionHash(ScaleValue actionHash) { + this.actionHash = actionHash; + } + + public ScaleValue getReturnCode() { + return returnCode; + } + + public void setReturnCode(ScaleValue returnCode) { + this.returnCode = returnCode; + } + + public String getObjCreator() { + return objCreator; + } + + public void setObjCreator(String objCreator) { + this.objCreator = objCreator; + } + + public String getObjName() { + return objName; + } + + public void setObjName(String objName) { + this.objName = objName; + } + + public Object getAuthPrivileges() { + return authPrivileges; + } + + public void setAuthPrivileges(Object authPrivileges) { + this.authPrivileges = authPrivileges; + } + + public Object getAuthGrantee() { + return authGrantee; + } + + public void setAuthGrantee(Object authGrantee) { + this.authGrantee = authGrantee; + } + + public Object getNewOwner() { + return newOwner; + } + + public void setNewOwner(Object newOwner) { + this.newOwner = newOwner; + } + + public Object getNewName() { + return newName; + } + + public void setNewName(Object newName) { + this.newName = newName; + } + + public Object getSesActions() { + return sesActions; + } + + public void setSesActions(Object sesActions) { + this.sesActions = sesActions; + } + + public Object getSesTid() { + return sesTid; + } + + public void setSesTid(Object sesTid) { + this.sesTid = sesTid; + } + + public Object getLogoffLread() { + return logoffLread; + } + + public void setLogoffLread(Object logoffLread) { + this.logoffLread = logoffLread; + } + + public Object getLogoffPread() { + return logoffPread; + } + + public void setLogoffPread(Object logoffPread) { + this.logoffPread = logoffPread; + } + + public Object getLogoffLwrite() { + return logoffLwrite; + } + + public void setLogoffLwrite(Object logoffLwrite) { + this.logoffLwrite = logoffLwrite; + } + + public Object getLogoffDead() { + return logoffDead; + } + + public void setLogoffDead(Object logoffDead) { + this.logoffDead = logoffDead; + } + + public Object getLogoffTime() { + return logoffTime; + } + + public void setLogoffTime(Object logoffTime) { + this.logoffTime = logoffTime; + } + + public Object getCommentText() { + return commentText; + } + + public void setCommentText(Object commentText) { + this.commentText = commentText; + } + + public Object getClientId() { + return clientId; + } + + public void setClientId(Object clientId) { + this.clientId = clientId; + } + + public String getSpare1() { + return spare1; + } + + public void setSpare1(String spare1) { + this.spare1 = spare1; + } + + public Object getSpare2() { + return spare2; + } + + public void setSpare2(Object spare2) { + this.spare2 = spare2; + } + + public Object getObjLabel() { + return objLabel; + } + + public void setObjLabel(Object objLabel) { + this.objLabel = objLabel; + } + + public Object getSesLabel() { + return sesLabel; + } + + public void setSesLabel(Object sesLabel) { + this.sesLabel = sesLabel; + } + + public Object getPrivUsed() { + return privUsed; + } + + public void setPrivUsed(Object privUsed) { + this.privUsed = privUsed; + } + + public Object getSessionCpu() { + return sessionCpu; + } + + public void setSessionCpu(Object sessionCpu) { + this.sessionCpu = sessionCpu; + } + + public Long getnTimestampHash() { + return nTimestampHash; + } + + public void setnTimestampHash(Long nTimestampHash) { + this.nTimestampHash = nTimestampHash; + } + + public Object getProxySid() { + return proxySid; + } + + public void setProxySid(Object proxySid) { + this.proxySid = proxySid; + } + + public Object getUserGuid() { + return userGuid; + } + + public void setUserGuid(Object userGuid) { + this.userGuid = userGuid; + } + + public ScaleValue getInstanceHash() { + return instanceHash; + } + + public void setInstanceHash(ScaleValue instanceHash) { + this.instanceHash = instanceHash; + } + + public String getProcessHash() { + return processHash; + } + + public void setProcessHash(String processHash) { + this.processHash = processHash; + } + + public String getXid() { + return xid; + } + + public void setXid(String xid) { + this.xid = xid; + } + + public Object getAuditId() { + return auditId; + } + + public void setAuditId(Object auditId) { + this.auditId = auditId; + } + + public ScaleValue getScn() { + return scn; + } + + public void setScn(ScaleValue scn) { + this.scn = scn; + } + + public ScaleValue getDbId() { + return dbId; + } + + public void setDbId(ScaleValue dbId) { + this.dbId = dbId; + } + + public String getSqlBind() { + return sqlBind; + } + + public void setSqlBind(String sqlBind) { + this.sqlBind = sqlBind; + } + + public String getSqlText() { + return sqlText; + } + + public void setSqlText(String sqlText) { + this.sqlText = sqlText; + } + + public Object getObjEdition() { + return objEdition; + } + + public void setObjEdition(Object objEdition) { + this.objEdition = objEdition; + } + + public Object getRlsInfo() { + return rlsInfo; + } + + public void setRlsInfo(Object rlsInfo) { + this.rlsInfo = rlsInfo; + } + + public String getCurrentUser() { + return currentUser; + } + + public void setCurrentUser(String currentUser) { + this.currentUser = currentUser; + } + + public AuditData() { + } + + public AuditData(ScaleValue sessionId, ScaleValue entryId, ScaleValue statement, Object timestampHash, String userId, String userHost, String terminal, ScaleValue actionHash, ScaleValue returnCode, String objCreator, String objName, Object authPrivileges, Object authGrantee, Object newOwner, Object newName, Object sesActions, Object sesTid, Object logoffLread, Object logoffPread, Object logoffLwrite, Object logoffDead, Object logoffTime, Object commentText, Object clientId, String spare1, Object spare2, Object objLabel, Object sesLabel, Object privUsed, Object sessionCpu, Long nTimestampHash, Object proxySid, Object userGuid, ScaleValue instanceHash, String processHash, String xid, Object auditId, ScaleValue scn, ScaleValue dbId, String sqlBind, String sqlText, Object objEdition, Object rlsInfo, String currentUser) { + this.sessionId = sessionId; + this.entryId = entryId; + this.statement = statement; + this.timestampHash = timestampHash; + this.userId = userId; + this.userHost = userHost; + this.terminal = terminal; + this.actionHash = actionHash; + this.returnCode = returnCode; + this.objCreator = objCreator; + this.objName = objName; + this.authPrivileges = authPrivileges; + this.authGrantee = authGrantee; + this.newOwner = newOwner; + this.newName = newName; + this.sesActions = sesActions; + this.sesTid = sesTid; + this.logoffLread = logoffLread; + this.logoffPread = logoffPread; + this.logoffLwrite = logoffLwrite; + this.logoffDead = logoffDead; + this.logoffTime = logoffTime; + this.commentText = commentText; + this.clientId = clientId; + this.spare1 = spare1; + this.spare2 = spare2; + this.objLabel = objLabel; + this.sesLabel = sesLabel; + this.privUsed = privUsed; + this.sessionCpu = sessionCpu; + this.nTimestampHash = nTimestampHash; + this.proxySid = proxySid; + this.userGuid = userGuid; + this.instanceHash = instanceHash; + this.processHash = processHash; + this.xid = xid; + this.auditId = auditId; + this.scn = scn; + this.dbId = dbId; + this.sqlBind = sqlBind; + this.sqlText = sqlText; + this.objEdition = objEdition; + this.rlsInfo = rlsInfo; + this.currentUser = currentUser; + } +} diff --git a/src/main/java/com/myapps/kafka/model/tres/AuditEvent.java b/src/main/java/com/myapps/kafka/model/tres/AuditEvent.java new file mode 100644 index 0000000..ec80489 --- /dev/null +++ b/src/main/java/com/myapps/kafka/model/tres/AuditEvent.java @@ -0,0 +1,84 @@ +package com.myapps.kafka.model.tres; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class AuditEvent { + @JsonProperty("before") + public AuditData before; + + @JsonProperty("after") + public AuditData after; + + @JsonProperty("source") + public Source source; + + @JsonProperty("op") + public String op; + + @JsonProperty("ts_ms") + public Long tsMs; + + @JsonProperty("transaction") + public Object transaction; + + + public AuditData getBefore() { + return before; + } + + public void setBefore(AuditData before) { + this.before = before; + } + + public AuditData getAfter() { + return after; + } + + public void setAfter(AuditData after) { + this.after = after; + } + + public Source getSource() { + return source; + } + + public void setSource(Source source) { + this.source = source; + } + + public String getOp() { + return op; + } + + public void setOp(String op) { + this.op = op; + } + + public Long getTsMs() { + return tsMs; + } + + public void setTsMs(Long tsMs) { + this.tsMs = tsMs; + } + + public Object getTransaction() { + return transaction; + } + + public void setTransaction(Object transaction) { + this.transaction = transaction; + } + + public AuditEvent() { + } + + public AuditEvent(AuditData before, AuditData after, Source source, String op, Long tsMs, Object transaction) { + this.before = before; + this.after = after; + this.source = source; + this.op = op; + this.tsMs = tsMs; + this.transaction = transaction; + } +} diff --git a/src/main/java/com/myapps/kafka/model/tres/ScaleValue.java b/src/main/java/com/myapps/kafka/model/tres/ScaleValue.java new file mode 100644 index 0000000..b3d0d78 --- /dev/null +++ b/src/main/java/com/myapps/kafka/model/tres/ScaleValue.java @@ -0,0 +1,35 @@ +package com.myapps.kafka.model.tres; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class ScaleValue { + @JsonProperty("scale") + public Integer scale; + + @JsonProperty("value") + public String value; + + public Integer getScale() { + return scale; + } + + public void setScale(Integer scale) { + this.scale = scale; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + public ScaleValue() { + } + + public ScaleValue(Integer scale, String value) { + this.scale = scale; + this.value = value; + } +} diff --git a/src/main/java/com/myapps/kafka/model/tres/Source.java b/src/main/java/com/myapps/kafka/model/tres/Source.java new file mode 100644 index 0000000..ecba445 --- /dev/null +++ b/src/main/java/com/myapps/kafka/model/tres/Source.java @@ -0,0 +1,215 @@ +package com.myapps.kafka.model.tres; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class Source { + @JsonProperty("version") + public String version; + + @JsonProperty("connector") + public String connector; + + @JsonProperty("name") + public String name; + + @JsonProperty("ts_ms") + public Long tsMs; + + @JsonProperty("snapshot") + public String snapshot; + + @JsonProperty("db") + public String db; + + @JsonProperty("sequence") + public Object sequence; + + @JsonProperty("schema") + public String schema; + + @JsonProperty("table") + public String table; + + @JsonProperty("txId") + public String txId; + + @JsonProperty("scn") + public String scn; + + @JsonProperty("commit_scn") + public String commitScn; + + @JsonProperty("lcr_position") + public Object lcrPosition; + + @JsonProperty("rs_id") + public Object rsId; + + @JsonProperty("ssn") + public Integer ssn; + + @JsonProperty("redo_thread") + public Integer redoThread; + + @JsonProperty("user_name") + public String userName; + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + + public String getConnector() { + return connector; + } + + public void setConnector(String connector) { + this.connector = connector; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Long getTsMs() { + return tsMs; + } + + public void setTsMs(Long tsMs) { + this.tsMs = tsMs; + } + + public String getSnapshot() { + return snapshot; + } + + public void setSnapshot(String snapshot) { + this.snapshot = snapshot; + } + + public String getDb() { + return db; + } + + public void setDb(String db) { + this.db = db; + } + + public Object getSequence() { + return sequence; + } + + public void setSequence(Object sequence) { + this.sequence = sequence; + } + + public String getSchema() { + return schema; + } + + public void setSchema(String schema) { + this.schema = schema; + } + + public String getTable() { + return table; + } + + public void setTable(String table) { + this.table = table; + } + + public String getTxId() { + return txId; + } + + public void setTxId(String txId) { + this.txId = txId; + } + + public String getScn() { + return scn; + } + + public void setScn(String scn) { + this.scn = scn; + } + + public String getCommitScn() { + return commitScn; + } + + public void setCommitScn(String commitScn) { + this.commitScn = commitScn; + } + + public Object getLcrPosition() { + return lcrPosition; + } + + public void setLcrPosition(Object lcrPosition) { + this.lcrPosition = lcrPosition; + } + + public Object getRsId() { + return rsId; + } + + public void setRsId(Object rsId) { + this.rsId = rsId; + } + + public Integer getSsn() { + return ssn; + } + + public void setSsn(Integer ssn) { + this.ssn = ssn; + } + + public Integer getRedoThread() { + return redoThread; + } + + public void setRedoThread(Integer redoThread) { + this.redoThread = redoThread; + } + + public String getUserName() { + return userName; + } + + public void setUserName(String userName) { + this.userName = userName; + } + + public Source() { + } + + public Source(String version, String connector, String name, Long tsMs, String snapshot, String db, Object sequence, String schema, String table, String txId, String scn, String commitScn, Object lcrPosition, Object rsId, Integer ssn, Integer redoThread, String userName) { + this.version = version; + this.connector = connector; + this.name = name; + this.tsMs = tsMs; + this.snapshot = snapshot; + this.db = db; + this.sequence = sequence; + this.schema = schema; + this.table = table; + this.txId = txId; + this.scn = scn; + this.commitScn = commitScn; + this.lcrPosition = lcrPosition; + this.rsId = rsId; + this.ssn = ssn; + this.redoThread = redoThread; + this.userName = userName; + } +} diff --git a/src/main/java/com/myapps/kafka/model/uno/Movimiento.java b/src/main/java/com/myapps/kafka/model/uno/Movimiento.java new file mode 100644 index 0000000..5dc52b0 --- /dev/null +++ b/src/main/java/com/myapps/kafka/model/uno/Movimiento.java @@ -0,0 +1,57 @@ +package com.myapps.kafka.model.uno; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class Movimiento { + @JsonProperty("ID") + private int id; + @JsonProperty("USUARIO_ID") + private int usuarioId; + @JsonProperty("MONTO") + private double monto; + @JsonProperty("FECHA") + private long fecha; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public int getUsuarioId() { + return usuarioId; + } + + public void setUsuarioId(int usuarioId) { + this.usuarioId = usuarioId; + } + + public double getMonto() { + return monto; + } + + public void setMonto(double monto) { + this.monto = monto; + } + + public long getFecha() { + return fecha; + } + + public void setFecha(long fecha) { + this.fecha = fecha; + } + + + public Movimiento() { + } + + public Movimiento(int id, int usuarioId, double monto, long fecha) { + this.id = id; + this.usuarioId = usuarioId; + this.monto = monto; + this.fecha = fecha; + } +} \ No newline at end of file diff --git a/src/main/java/com/myapps/kafka/model/uno/Source.java b/src/main/java/com/myapps/kafka/model/uno/Source.java new file mode 100644 index 0000000..9d89a42 --- /dev/null +++ b/src/main/java/com/myapps/kafka/model/uno/Source.java @@ -0,0 +1,189 @@ +package com.myapps.kafka.model.uno; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class Source { + private String version; + private String connector; + private String name; + @JsonProperty("ts_ms") + private long tsMs; + private String snapshot; + private String db; + private String sequence; + private String schema; + private String table; + private String txId; + private String scn; + @JsonProperty("commit_scn") + private String commitScn; + @JsonProperty("lcr_position") + private String lcrPosition; + @JsonProperty("rs_id") + private String rsId; + private int ssn; + @JsonProperty("redo_thread") + private String redoThread; + @JsonProperty("user_name") + private String userName; + + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + + public String getConnector() { + return connector; + } + + public void setConnector(String connector) { + this.connector = connector; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public long getTsMs() { + return tsMs; + } + + public void setTsMs(long tsMs) { + this.tsMs = tsMs; + } + + public String getSnapshot() { + return snapshot; + } + + public void setSnapshot(String snapshot) { + this.snapshot = snapshot; + } + + public String getDb() { + return db; + } + + public void setDb(String db) { + this.db = db; + } + + public String getSequence() { + return sequence; + } + + public void setSequence(String sequence) { + this.sequence = sequence; + } + + public String getSchema() { + return schema; + } + + public void setSchema(String schema) { + this.schema = schema; + } + + public String getTable() { + return table; + } + + public void setTable(String table) { + this.table = table; + } + + public String getTxId() { + return txId; + } + + public void setTxId(String txId) { + this.txId = txId; + } + + public String getScn() { + return scn; + } + + public void setScn(String scn) { + this.scn = scn; + } + + public String getCommitScn() { + return commitScn; + } + + public void setCommitScn(String commitScn) { + this.commitScn = commitScn; + } + + public String getLcrPosition() { + return lcrPosition; + } + + public void setLcrPosition(String lcrPosition) { + this.lcrPosition = lcrPosition; + } + + public String getRsId() { + return rsId; + } + + public void setRsId(String rsId) { + this.rsId = rsId; + } + + public int getSsn() { + return ssn; + } + + public void setSsn(int ssn) { + this.ssn = ssn; + } + + public String getRedoThread() { + return redoThread; + } + + public void setRedoThread(String redoThread) { + this.redoThread = redoThread; + } + + public String getUserName() { + return userName; + } + + public void setUserName(String userName) { + this.userName = userName; + } + + public Source() { + } + + public Source(String version, String connector, String name, long tsMs, String snapshot, String db, String sequence, String schema, String table, String txId, String scn, String commitScn, String lcrPosition, String rsId, int ssn, String redoThread, String userName) { + this.version = version; + this.connector = connector; + this.name = name; + this.tsMs = tsMs; + this.snapshot = snapshot; + this.db = db; + this.sequence = sequence; + this.schema = schema; + this.table = table; + this.txId = txId; + this.scn = scn; + this.commitScn = commitScn; + this.lcrPosition = lcrPosition; + this.rsId = rsId; + this.ssn = ssn; + this.redoThread = redoThread; + this.userName = userName; + } +} diff --git a/src/main/java/com/myapps/kafka/model/uno/Transaccion.java b/src/main/java/com/myapps/kafka/model/uno/Transaccion.java new file mode 100644 index 0000000..e48b5c8 --- /dev/null +++ b/src/main/java/com/myapps/kafka/model/uno/Transaccion.java @@ -0,0 +1,74 @@ +package com.myapps.kafka.model.uno; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class Transaccion { + private Movimiento before; + private Movimiento after; + private Source source; + private String op; + @JsonProperty("ts_ms") + private long tsMs; + private String transaction; + + public Movimiento getBefore() { + return before; + } + + public void setBefore(Movimiento before) { + this.before = before; + } + + public Movimiento getAfter() { + return after; + } + + public void setAfter(Movimiento movimiento) { + this.after = movimiento; + } + + public Source getSource() { + return source; + } + + public void setSource(Source source) { + this.source = source; + } + + public String getOp() { + return op; + } + + public void setOp(String op) { + this.op = op; + } + + public long getTsMs() { + return tsMs; + } + + public void setTsMs(long tsMs) { + this.tsMs = tsMs; + } + + public String getTransaction() { + return transaction; + } + + public void setTransaction(String transaction) { + this.transaction = transaction; + } + + public Transaccion() { + } + + public Transaccion(Movimiento before, Movimiento after, Source source, String op, long tsMs, String transaction) { + this.before = before; + this.after = after; + this.source = source; + this.op = op; + this.tsMs = tsMs; + this.transaction = transaction; + } +} + diff --git a/src/main/java/com/myapps/kafka/producer/KafkaProducerConfig.java b/src/main/java/com/myapps/kafka/producer/KafkaProducerConfig.java new file mode 100644 index 0000000..3eca0a9 --- /dev/null +++ b/src/main/java/com/myapps/kafka/producer/KafkaProducerConfig.java @@ -0,0 +1,31 @@ +package com.myapps.kafka.producer; + +import org.apache.kafka.clients.producer.ProducerConfig; +import org.apache.kafka.common.serialization.StringSerializer; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.kafka.core.DefaultKafkaProducerFactory; +import org.springframework.kafka.core.KafkaTemplate; +import org.springframework.kafka.core.ProducerFactory; + +import java.util.HashMap; +import java.util.Map; +// +//@Configuration +//public class KafkaProducerConfig { +// +// @Bean +// public ProducerFactory producerFactory() { +// Map configProps = new HashMap<>(); +// configProps.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, "127.0.0.1:9092"); +// configProps.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class); +// configProps.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class); +// return new DefaultKafkaProducerFactory<>(configProps); +// } +// +// @Bean +// public KafkaTemplate kafkaTemplate() { +// return new KafkaTemplate<>(producerFactory()); +// } +//} + diff --git a/src/main/java/com/myapps/kafka/producer/KafkaProducerService.java b/src/main/java/com/myapps/kafka/producer/KafkaProducerService.java new file mode 100644 index 0000000..3e63d21 --- /dev/null +++ b/src/main/java/com/myapps/kafka/producer/KafkaProducerService.java @@ -0,0 +1,19 @@ +package com.myapps.kafka.producer; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.kafka.core.KafkaTemplate; +import org.springframework.stereotype.Service; + +@Service +public class KafkaProducerService { + + private static final String TOPIC = "alertas-raw"; + + @Autowired + private KafkaTemplate kafkaTemplate; + + public void sendMessage(String message) { + kafkaTemplate.send(TOPIC, message); + } +} + diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties new file mode 100644 index 0000000..eaff8b2 --- /dev/null +++ b/src/main/resources/application.properties @@ -0,0 +1,28 @@ +spring.application.name=demoKafka + +server.port=8087 +# Kafka +spring.kafka.bootstrap-servers=host.docker.internal:9092 +spring.kafka.consumer.group-id=fraude-consumer-group +spring.kafka.consumer.auto-offset-reset=earliest +spring.kafka.consumer.key-deserializer=org.apache.kafka.common.serialization.StringDeserializer +spring.kafka.consumer.value-deserializer=org.apache.kafka.common.serialization.StringDeserializer +spring.kafka.consumer.enable-auto-commit=false + + + +#spring.mail.host=smtp.ipage.com +#spring.mail.port=995 +#spring.mail.username=miguel.claure@myapps.com.bo +#spring.mail.password=-MiguelC1209 +#spring.mail.properties.mail.smtp.auth=false +#spring.mail.properties.mail.smtp.starttls.enable=true + + + +spring.mail.host=localhost +spring.mail.port=1025 +spring.mail.username= +spring.mail.password= +spring.mail.properties.mail.smtp.auth=false +spring.mail.properties.mail.smtp.starttls.enable=false diff --git a/src/test/java/com/myapps/kafka/DemoKafkaApplicationTests.java b/src/test/java/com/myapps/kafka/DemoKafkaApplicationTests.java new file mode 100644 index 0000000..afdc9bf --- /dev/null +++ b/src/test/java/com/myapps/kafka/DemoKafkaApplicationTests.java @@ -0,0 +1,13 @@ +package com.myapps.kafka; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class DemoKafkaApplicationTests { + + @Test + void contextLoads() { + } + +}