diff --git a/gradle/win/kamco-dabeeo-backoffice_gradle.tar.gz b/gradle/win/kamco-dabeeo-backoffice_gradle.tar.gz new file mode 100755 index 00000000..bcc4932f Binary files /dev/null and b/gradle/win/kamco-dabeeo-backoffice_gradle.tar.gz differ diff --git a/gradle/win/scripts/Readme.txt b/gradle/win/scripts/Readme.txt new file mode 100755 index 00000000..03c24ff4 --- /dev/null +++ b/gradle/win/scripts/Readme.txt @@ -0,0 +1,14 @@ +How to Use + +[1] Move The Two scripts to a Last location +1. pack_offline_bundle_airgap.ps1 +2. unpack_and_offline_build_airgap.ps1 + +[2] Packing Scripts Start --Options: Internet connect Require when you packing, after then you will get all gradle File +command on powershell: powershell -ExecutionPolicy Bypass -File .\pack_offline_bundle_airgap.ps1 + +[3] UnPacking Scripts Start --Options: The JPA Spring boot Project All gradle, gradle cache File, Build File etc (Check using .\gradlew.bat bootRun --offline) +command on powershell: powershell -ExecutionPolicy Bypass -File .\unpack_and_offline_build_airgap.ps1 .\kamco-dabeeo-backoffice_offline_bundle_20260121_145830.tar.gz (The tar File name have to be changed) + + +PS. You can check the ALL Gradle Backup File location Users/d-pn-0071/Desktop/lala/kamco-dabeeo-backoffice/gradle/win/kamco-dabeeo-backoffice_gradle.tar.gz \ No newline at end of file diff --git a/gradle/win/scripts/pack_offline_bundle_airgap.ps1 b/gradle/win/scripts/pack_offline_bundle_airgap.ps1 new file mode 100755 index 00000000..35e2b995 --- /dev/null +++ b/gradle/win/scripts/pack_offline_bundle_airgap.ps1 @@ -0,0 +1,672 @@ +# pack_offline_bundle_airgap.ps1 +# ============================================================================ +# Gradle Offline Bundle Packer +# ============================================================================ +# Version: 4.0 +# +# WORKFLOW: +# 1. [ONLINE] Build project (./gradlew.bat bootJar) - downloads all deps +# 2. [ONLINE] Test run (./gradlew.bat bootRun) - verify app works +# 3. [OFFLINE TEST] Verify offline build works +# 4. Create bundle with all cached dependencies +# +# REQUIREMENTS: +# - Internet connection (for initial build) +# - Project with gradlew.bat +# ============================================================================ + +$ErrorActionPreference = "Stop" +$ProgressPreference = "SilentlyContinue" + +# ============================================================================ +# Configuration +# ============================================================================ +$WRAPPER_SEED_PATH = "wrapper_jar_seed" +$OFFLINE_HOME_NAME = "_offline_gradle_home" +$BOOTRUN_TIMEOUT_SECONDS = 60 + +Write-Host "" +Write-Host "============================================================" -ForegroundColor Cyan +Write-Host " Gradle Offline Bundle Packer v4.0" -ForegroundColor Cyan +Write-Host "============================================================" -ForegroundColor Cyan +Write-Host "" +Write-Host " This script will:" -ForegroundColor White +Write-Host " 1. Build project with internet (download dependencies)" -ForegroundColor Gray +Write-Host " 2. Test run application (verify it works)" -ForegroundColor Gray +Write-Host " 3. Test offline build (verify cache is complete)" -ForegroundColor Gray +Write-Host " 4. Create offline bundle for air-gapped environment" -ForegroundColor Gray +Write-Host "" +Write-Host "============================================================" -ForegroundColor Cyan +Write-Host "" + +# ============================================================================ +# [1/20] Check Current Directory +# ============================================================================ +Write-Host "==[1/20] Check Current Directory ==" -ForegroundColor Yellow +$Root = (Get-Location).Path +Write-Host ("ROOT_DIR: " + $Root) +Write-Host "" + +# ============================================================================ +# [2/20] Check Required Files +# ============================================================================ +Write-Host "==[2/20] Check Required Files ==" -ForegroundColor Yellow + +if (!(Test-Path -LiteralPath ".\gradlew.bat")) { + throw "ERROR: gradlew.bat not found. Run from project root." +} +Write-Host "[OK] gradlew.bat" -ForegroundColor Green + +$buildFile = $null +if (Test-Path -LiteralPath ".\build.gradle") { $buildFile = "build.gradle" } +elseif (Test-Path -LiteralPath ".\build.gradle.kts") { $buildFile = "build.gradle.kts" } +else { throw "ERROR: build.gradle(.kts) not found." } +Write-Host ("[OK] " + $buildFile) -ForegroundColor Green + +$settingsFile = $null +if (Test-Path -LiteralPath ".\settings.gradle") { $settingsFile = "settings.gradle" } +elseif (Test-Path -LiteralPath ".\settings.gradle.kts") { $settingsFile = "settings.gradle.kts" } +if ($settingsFile) { Write-Host ("[OK] " + $settingsFile) -ForegroundColor Green } +Write-Host "" + +# ============================================================================ +# [3/20] Check Gradle Wrapper +# ============================================================================ +Write-Host "==[3/20] Check Gradle Wrapper ==" -ForegroundColor Yellow + +$WrapperDir = Join-Path $Root "gradle\wrapper" +$WrapperJar = Join-Path $WrapperDir "gradle-wrapper.jar" +$WrapperProp = Join-Path $WrapperDir "gradle-wrapper.properties" + +New-Item -ItemType Directory -Force -Path $WrapperDir | Out-Null + +if (!(Test-Path -LiteralPath $WrapperProp)) { + throw "ERROR: gradle-wrapper.properties not found." +} + +if (!(Test-Path -LiteralPath $WrapperJar)) { + $SeedJar = Join-Path $Root "$WRAPPER_SEED_PATH\gradle-wrapper.jar" + if (Test-Path -LiteralPath $SeedJar) { + Copy-Item -Force -LiteralPath $SeedJar -Destination $WrapperJar + Write-Host "[OK] Wrapper jar injected from seed" -ForegroundColor Green + } else { + throw "ERROR: gradle-wrapper.jar missing" + } +} else { + Write-Host "[OK] gradle-wrapper.jar exists" -ForegroundColor Green +} + +# Create seed backup +$SeedDir = Join-Path $Root $WRAPPER_SEED_PATH +if (!(Test-Path -LiteralPath $SeedDir)) { + New-Item -ItemType Directory -Force -Path $SeedDir | Out-Null + Copy-Item -Force -LiteralPath $WrapperJar -Destination (Join-Path $SeedDir "gradle-wrapper.jar") +} +Write-Host "" + +# ============================================================================ +# [4/20] Set GRADLE_USER_HOME (Project Local) +# ============================================================================ +Write-Host "==[4/20] Set GRADLE_USER_HOME ==" -ForegroundColor Yellow + +$OfflineHome = Join-Path $Root $OFFLINE_HOME_NAME +New-Item -ItemType Directory -Force -Path $OfflineHome | Out-Null +$env:GRADLE_USER_HOME = $OfflineHome + +Write-Host ("GRADLE_USER_HOME = " + $env:GRADLE_USER_HOME) -ForegroundColor Cyan +Write-Host "[INFO] All dependencies will be cached in project folder" -ForegroundColor Gray +Write-Host "" + +# ============================================================================ +# [5/20] Check Internet Connection +# ============================================================================ +Write-Host "==[5/20] Check Internet Connection ==" -ForegroundColor Yellow + +$hasInternet = $false +$testHosts = @("plugins.gradle.org", "repo.maven.apache.org", "repo1.maven.org") + +foreach ($testHost in $testHosts) { + try { + $result = Test-Connection -ComputerName $testHost -Count 1 -Quiet -TimeoutSeconds 3 -ErrorAction SilentlyContinue + if ($result) { + $hasInternet = $true + Write-Host ("[OK] Connected to " + $testHost) -ForegroundColor Green + break + } + } catch { } +} + +if (-not $hasInternet) { + # Try DNS resolution as fallback + try { + [System.Net.Dns]::GetHostAddresses("google.com") | Out-Null + $hasInternet = $true + Write-Host "[OK] Internet available (DNS)" -ForegroundColor Green + } catch { } +} + +if (-not $hasInternet) { + Write-Host "" + Write-Host "============================================================" -ForegroundColor Red + Write-Host " ERROR: No Internet Connection!" -ForegroundColor Red + Write-Host "============================================================" -ForegroundColor Red + Write-Host "" + Write-Host "This script requires internet for initial build." -ForegroundColor Yellow + Write-Host "Please connect to internet and run again." -ForegroundColor Yellow + Write-Host "" + throw "No internet connection" +} +Write-Host "" + +# ============================================================================ +# [6/20] Initial Gradle Setup +# ============================================================================ +Write-Host "==[6/20] Initial Gradle Setup ==" -ForegroundColor Yellow +Write-Host "[INFO] Downloading Gradle distribution..." -ForegroundColor Gray + +try { + $output = cmd /c ".\gradlew.bat --version 2>&1" + if ($LASTEXITCODE -eq 0) { + $gradleVersion = $output | Select-String "Gradle\s+(\d+\.\d+)" | + ForEach-Object { $_.Matches[0].Groups[1].Value } + Write-Host ("[OK] Gradle " + $gradleVersion) -ForegroundColor Green + } else { + throw "Gradle setup failed" + } +} catch { + Write-Host "[ERROR] Gradle setup failed" -ForegroundColor Red + throw $_ +} +Write-Host "" + +# ============================================================================ +# [7/20] ONLINE BUILD - bootJar (Download All Dependencies) +# ============================================================================ +Write-Host "==[7/20] ONLINE BUILD - bootJar ==" -ForegroundColor Yellow +Write-Host "" +Write-Host "============================================================" -ForegroundColor Cyan +Write-Host " Building project (downloading all dependencies)" -ForegroundColor Cyan +Write-Host " This may take several minutes on first run..." -ForegroundColor Cyan +Write-Host "============================================================" -ForegroundColor Cyan +Write-Host "" + +$buildSuccess = $false + +try { + cmd /c ".\gradlew.bat clean bootJar --no-daemon" + if ($LASTEXITCODE -eq 0) { + $buildSuccess = $true + } +} catch { } + +if (-not $buildSuccess) { + Write-Host "" + Write-Host "============================================================" -ForegroundColor Red + Write-Host " BUILD FAILED!" -ForegroundColor Red + Write-Host "============================================================" -ForegroundColor Red + Write-Host "" + Write-Host "Please fix build errors and run this script again." -ForegroundColor Yellow + throw "Build failed" +} + +Write-Host "" +Write-Host "[OK] bootJar build SUCCESS" -ForegroundColor Green +Write-Host "" + +# ============================================================================ +# [8/20] ONLINE TEST - bootRun (Verify Application Works) +# ============================================================================ +Write-Host "==[8/20] ONLINE TEST - bootRun ==" -ForegroundColor Yellow +Write-Host "" +Write-Host "============================================================" -ForegroundColor Cyan +Write-Host " Starting application to verify it works..." -ForegroundColor Cyan +Write-Host " Will run for $BOOTRUN_TIMEOUT_SECONDS seconds then stop" -ForegroundColor Cyan +Write-Host "============================================================" -ForegroundColor Cyan +Write-Host "" + +$bootRunSuccess = $false + +try { + # Start bootRun as background job + $job = Start-Job -ScriptBlock { + param($projectDir, $gradleHome) + Set-Location $projectDir + $env:GRADLE_USER_HOME = $gradleHome + cmd /c ".\gradlew.bat bootRun --no-daemon 2>&1" + } -ArgumentList $Root, $OfflineHome + + Write-Host "[INFO] Application starting..." -ForegroundColor Gray + + # Wait for startup (check for typical Spring Boot messages) + $startTime = Get-Date + $startupDetected = $false + + while (((Get-Date) - $startTime).TotalSeconds -lt $BOOTRUN_TIMEOUT_SECONDS) { + Start-Sleep -Seconds 3 + + # Check if job has output + $jobOutput = Receive-Job -Job $job -Keep -ErrorAction SilentlyContinue + + if ($jobOutput) { + $outputText = $jobOutput -join "`n" + + # Check for Spring Boot startup success indicators + if ($outputText -match "Started .+ in .+ seconds" -or + $outputText -match "Tomcat started on port" -or + $outputText -match "Netty started on port" -or + $outputText -match "Application .+ started") { + $startupDetected = $true + Write-Host "[OK] Application started successfully!" -ForegroundColor Green + break + } + + # Check for errors + if ($outputText -match "APPLICATION FAILED TO START" -or + $outputText -match "Error starting ApplicationContext") { + Write-Host "[ERROR] Application failed to start" -ForegroundColor Red + break + } + } + + $elapsed = [math]::Round(((Get-Date) - $startTime).TotalSeconds) + Write-Host ("[INFO] Waiting... " + $elapsed + "s") -ForegroundColor Gray + } + + # Stop the job + Write-Host "[INFO] Stopping application..." -ForegroundColor Gray + Stop-Job -Job $job -ErrorAction SilentlyContinue + Remove-Job -Job $job -Force -ErrorAction SilentlyContinue + + # Also stop any remaining Gradle processes + cmd /c ".\gradlew.bat --stop 2>&1" | Out-Null + + if ($startupDetected) { + $bootRunSuccess = $true + } + +} catch { + Write-Host "[WARN] bootRun test encountered error: $_" -ForegroundColor DarkYellow +} + +# Cleanup any remaining processes +try { + Get-Process -Name "java" -ErrorAction SilentlyContinue | + Where-Object { $_.CommandLine -match "bootRun|spring" } | + Stop-Process -Force -ErrorAction SilentlyContinue +} catch { } + +Write-Host "" + +if ($bootRunSuccess) { + Write-Host "[OK] bootRun test PASSED" -ForegroundColor Green +} else { + Write-Host "[WARN] bootRun test could not verify startup" -ForegroundColor DarkYellow + Write-Host "[INFO] Continuing anyway - bootJar succeeded" -ForegroundColor Gray +} +Write-Host "" + +# ============================================================================ +# [9/20] Stop All Gradle Daemons +# ============================================================================ +Write-Host "==[9/20] Stop Gradle Daemons ==" -ForegroundColor Yellow + +cmd /c ".\gradlew.bat --stop 2>&1" | Out-Null +Start-Sleep -Seconds 3 +Write-Host "[OK] Daemons stopped" -ForegroundColor Green +Write-Host "" + +# ============================================================================ +# [10/20] OFFLINE TEST - Verify Offline Build Works +# ============================================================================ +Write-Host "==[10/20] OFFLINE TEST - Verify Cache ==" -ForegroundColor Yellow +Write-Host "" +Write-Host "============================================================" -ForegroundColor Cyan +Write-Host " Testing offline build (--offline flag)" -ForegroundColor Cyan +Write-Host " This verifies all dependencies are cached" -ForegroundColor Cyan +Write-Host "============================================================" -ForegroundColor Cyan +Write-Host "" + +$offlineSuccess = $false + +try { + cmd /c ".\gradlew.bat --offline clean bootJar --no-daemon" + if ($LASTEXITCODE -eq 0) { + $offlineSuccess = $true + } +} catch { } + +Write-Host "" + +if ($offlineSuccess) { + Write-Host "[OK] Offline build SUCCESS - Cache is complete!" -ForegroundColor Green +} else { + Write-Host "============================================================" -ForegroundColor Red + Write-Host " OFFLINE BUILD FAILED!" -ForegroundColor Red + Write-Host "============================================================" -ForegroundColor Red + Write-Host "" + Write-Host "Some dependencies may not be cached properly." -ForegroundColor Yellow + Write-Host "" + + $continue = Read-Host "Continue creating bundle anyway? (y/N)" + if ($continue -ne "y" -and $continue -ne "Y") { + throw "Offline verification failed" + } +} +Write-Host "" + +# ============================================================================ +# [11/20] Backup Original settings.gradle +# ============================================================================ +Write-Host "==[11/20] Backup settings.gradle ==" -ForegroundColor Yellow + +if ($settingsFile) { + $settingsPath = Join-Path $Root $settingsFile + $settingsBackup = Join-Path $Root "${settingsFile}.original.bak" + + if (!(Test-Path -LiteralPath $settingsBackup)) { + Copy-Item -Force -LiteralPath $settingsPath -Destination $settingsBackup + Write-Host "[OK] Backup: ${settingsFile}.original.bak" -ForegroundColor Green + } else { + Write-Host "[OK] Backup exists" -ForegroundColor Green + } +} +Write-Host "" + +# ============================================================================ +# [12/20] Modify settings.gradle for Offline +# ============================================================================ +Write-Host "==[12/20] Configure settings.gradle for Offline ==" -ForegroundColor Yellow + +if ($settingsFile) { + $settingsPath = Join-Path $Root $settingsFile + $content = Get-Content -LiteralPath $settingsPath -Raw + + # --- Always strip BOM if present (prevents Groovy 'Unexpected character: ') + $hadBom = $false + if ($content.Length -gt 0 -and $content[0] -eq [char]0xFEFF) { + $hadBom = $true + $content = $content -replace "^\uFEFF", "" + } + + $isOfflineConfigured = + ($content -match "mavenLocal\(\)") -and + ($content -match "pluginManagement[\s\S]*repositories") + + if ($isOfflineConfigured) { + # Even if already configured, re-save without BOM if needed + if ($hadBom) { + [System.IO.File]::WriteAllText( + $settingsPath, + $content, + (New-Object System.Text.UTF8Encoding($false)) + ) + Write-Host "[FIX] settings.gradle BOM removed (saved as UTF-8 without BOM)" -ForegroundColor Green + } else { + Write-Host "[OK] Already configured for offline" -ForegroundColor Green + } + } else { + $newHeader = @" +// ============================================================================ +// OFFLINE BUILD CONFIGURATION (Auto-generated by pack script) +// Original backup: ${settingsFile}.original.bak +// ============================================================================ +pluginManagement { + repositories { + mavenLocal() + gradlePluginPortal() + } +} + +"@ + + # Remove existing pluginManagement + $cleaned = $content -replace '(?s)pluginManagement\s*\{[^{}]*(\{[^{}]*\}[^{}]*)*\}\s*', '' + $final = $newHeader + $cleaned.Trim() + + # --- Write as UTF-8 WITHOUT BOM + [System.IO.File]::WriteAllText( + $settingsPath, + $final, + (New-Object System.Text.UTF8Encoding($false)) + ) + + Write-Host "[OK] settings.gradle updated for offline (UTF-8 without BOM)" -ForegroundColor Green + } +} +Write-Host "" + +# ============================================================================ +# [13/20] Copy Maven Local Repository +# ============================================================================ +Write-Host "==[13/20] Copy Maven Local (.m2) ==" -ForegroundColor Yellow + +$m2Repo = Join-Path $env:USERPROFILE ".m2\repository" +$localM2 = Join-Path $OfflineHome "m2_repository" + +if (Test-Path -LiteralPath $m2Repo) { + $m2Size = (Get-ChildItem -Path $m2Repo -Recurse -File -ErrorAction SilentlyContinue | + Measure-Object -Property Length -Sum).Sum + + if ($m2Size -gt 1MB) { + $m2SizeMB = [math]::Round($m2Size / 1MB, 2) + Write-Host ("[INFO] .m2 size: " + $m2SizeMB + " MB") -ForegroundColor Cyan + + # Copy important plugin directories + $pluginDirs = @( + "org\springframework\boot", + "io\spring", + "com\diffplug" + ) + + foreach ($dir in $pluginDirs) { + $src = Join-Path $m2Repo $dir + if (Test-Path -LiteralPath $src) { + $dst = Join-Path $localM2 $dir + New-Item -ItemType Directory -Force -Path (Split-Path $dst -Parent) | Out-Null + if (!(Test-Path -LiteralPath $dst)) { + Copy-Item -Recurse -Force -LiteralPath $src -Destination $dst -ErrorAction SilentlyContinue + Write-Host ("[OK] Copied " + $dir) -ForegroundColor Green + } + } + } + } +} else { + Write-Host "[INFO] No .m2 repository found" -ForegroundColor Gray +} +Write-Host "" + +# ============================================================================ +# [14/20] Create Helper Scripts +# ============================================================================ +Write-Host "==[14/20] Create Helper Scripts ==" -ForegroundColor Yellow + +# run_offline_build.ps1 +$runScript = @' +# run_offline_build.ps1 - Quick offline build script +$env:GRADLE_USER_HOME = Join-Path (Get-Location).Path "_offline_gradle_home" +Write-Host "GRADLE_USER_HOME = $env:GRADLE_USER_HOME" -ForegroundColor Cyan +Write-Host "" +.\gradlew.bat --offline bootJar --no-daemon +if ($LASTEXITCODE -eq 0) { + Write-Host "" + Write-Host "BUILD SUCCESS!" -ForegroundColor Green + Write-Host "" + Write-Host "JAR files:" -ForegroundColor Cyan + Get-ChildItem .\build\libs\*.jar | ForEach-Object { Write-Host (" " + $_.Name) } +} else { + Write-Host "BUILD FAILED" -ForegroundColor Red +} +'@ + +[System.IO.File]::WriteAllText((Join-Path $Root "run_offline_build.ps1"), $runScript, (New-Object System.Text.UTF8Encoding($false))) +Write-Host "[OK] run_offline_build.ps1" -ForegroundColor Green + +# run_offline_bootrun.ps1 +$bootRunScript = @' +# run_offline_bootrun.ps1 - Run application offline +$env:GRADLE_USER_HOME = Join-Path (Get-Location).Path "_offline_gradle_home" +Write-Host "GRADLE_USER_HOME = $env:GRADLE_USER_HOME" -ForegroundColor Cyan +Write-Host "" +Write-Host "Starting application (Ctrl+C to stop)..." -ForegroundColor Yellow +Write-Host "" +.\gradlew.bat --offline bootRun --no-daemon +'@ + +[System.IO.File]::WriteAllText((Join-Path $Root "run_offline_bootrun.ps1"), $bootRunScript, (New-Object System.Text.UTF8Encoding($false))) +Write-Host "[OK] run_offline_bootrun.ps1" -ForegroundColor Green +Write-Host "" + +# ============================================================================ +# [15/20] Stop Daemons Again +# ============================================================================ +Write-Host "==[15/20] Final Daemon Cleanup ==" -ForegroundColor Yellow + +cmd /c ".\gradlew.bat --stop 2>&1" | Out-Null +Start-Sleep -Seconds 2 +Write-Host "[OK] Daemons stopped" -ForegroundColor Green +Write-Host "" + +# ============================================================================ +# [16/20] Clean Lock Files +# ============================================================================ +Write-Host "==[16/20] Clean Lock Files ==" -ForegroundColor Yellow + +try { + $DaemonDir = Join-Path $OfflineHome "daemon" + if (Test-Path -LiteralPath $DaemonDir) { + Remove-Item -Recurse -Force -LiteralPath $DaemonDir -ErrorAction SilentlyContinue + } + + Get-ChildItem -Path $OfflineHome -Recurse -Include "*.lock","*.log","*.tmp" -File -ErrorAction SilentlyContinue | + ForEach-Object { Remove-Item -Force -LiteralPath $_.FullName -ErrorAction SilentlyContinue } + + Write-Host "[OK] Lock files cleaned" -ForegroundColor Green +} catch { + Write-Host "[WARN] Some files could not be cleaned" -ForegroundColor DarkYellow +} +Write-Host "" + +# ============================================================================ +# [17/20] Calculate Cache Size +# ============================================================================ +Write-Host "==[17/20] Cache Summary ==" -ForegroundColor Yellow + +$CachesDir = Join-Path $OfflineHome "caches" +$WrapperDists = Join-Path $OfflineHome "wrapper\dists" + +$totalSize = 0 + +if (Test-Path -LiteralPath $CachesDir) { + $size = (Get-ChildItem -Path $CachesDir -Recurse -File -ErrorAction SilentlyContinue | + Measure-Object -Property Length -Sum).Sum + $totalSize += $size + Write-Host ("[INFO] Dependencies: " + [math]::Round($size/1MB, 2) + " MB") -ForegroundColor Cyan +} + +if (Test-Path -LiteralPath $WrapperDists) { + $size = (Get-ChildItem -Path $WrapperDists -Recurse -File -ErrorAction SilentlyContinue | + Measure-Object -Property Length -Sum).Sum + $totalSize += $size + Write-Host ("[INFO] Gradle dist: " + [math]::Round($size/1MB, 2) + " MB") -ForegroundColor Cyan +} + +Write-Host ("[INFO] Total cache: " + [math]::Round($totalSize/1MB, 2) + " MB") -ForegroundColor Cyan +Write-Host "" + +# ============================================================================ +# [18/20] Create Archive +# ============================================================================ +Write-Host "==[18/20] Create Archive ==" -ForegroundColor Yellow + +$BaseName = Split-Path $Root -Leaf +$Ts = Get-Date -Format "yyyyMMdd_HHmmss" +$Parent = Split-Path $Root -Parent +$ArchivePath = Join-Path $Parent "${BaseName}_offline_bundle_${Ts}.tar.gz" + +Write-Host ("Archive: " + $ArchivePath) + +$tar = Get-Command tar.exe -ErrorAction SilentlyContinue +if (-not $tar) { throw "ERROR: tar.exe not found" } + +Write-Host "[INFO] Creating archive (this may take several minutes)..." -ForegroundColor Gray + +& tar.exe -czf $ArchivePath ` + --exclude ".git" ` + --exclude ".idea" ` + --exclude ".DS_Store" ` + --exclude "*.log" ` + --exclude "*.lock" ` + --exclude "_offline_gradle_home/daemon" ` + --exclude "_offline_gradle_home/native" ` + --exclude "_offline_gradle_home/jdks" ` + --exclude "build" ` + --exclude "out" ` + --exclude ".gradle" ` + -C $Root . + +if ($LASTEXITCODE -ne 0) { throw "ERROR: tar failed" } + +$archiveSize = (Get-Item -LiteralPath $ArchivePath).Length +$archiveSizeMB = [math]::Round($archiveSize / 1MB, 2) +Write-Host ("[OK] Archive created: " + $archiveSizeMB + " MB") -ForegroundColor Green +Write-Host "" + +# ============================================================================ +# [19/20] Verify Archive +# ============================================================================ +Write-Host "==[19/20] Verify Archive ==" -ForegroundColor Yellow + +$listOutput = & tar.exe -tzf $ArchivePath 2>&1 + +$checks = @( + "gradle/wrapper/gradle-wrapper.jar", + "gradlew.bat", + "_offline_gradle_home/caches", + "run_offline_build.ps1" +) + +foreach ($check in $checks) { + $found = $listOutput | Select-String -SimpleMatch $check + if ($found) { + Write-Host (" [OK] " + $check) -ForegroundColor Green + } else { + Write-Host (" [WARN] " + $check) -ForegroundColor DarkYellow + } +} +Write-Host "" + +# ============================================================================ +# [20/20] Complete +# ============================================================================ +Write-Host "============================================================" -ForegroundColor Green +Write-Host " BUNDLE CREATION COMPLETE!" -ForegroundColor Green +Write-Host "============================================================" -ForegroundColor Green +Write-Host "" +Write-Host ("Archive: " + $ArchivePath) -ForegroundColor Cyan +Write-Host ("Size: " + $archiveSizeMB + " MB") -ForegroundColor Cyan +Write-Host "" + +Write-Host "============================================================" -ForegroundColor Cyan +Write-Host " Test Results" -ForegroundColor Cyan +Write-Host "============================================================" -ForegroundColor Cyan +Write-Host (" Online build (bootJar): " + $(if($buildSuccess){"PASSED"}else{"FAILED"})) -ForegroundColor $(if($buildSuccess){"Green"}else{"Red"}) +Write-Host (" Online test (bootRun): " + $(if($bootRunSuccess){"PASSED"}else{"SKIPPED"})) -ForegroundColor $(if($bootRunSuccess){"Green"}else{"Yellow"}) +Write-Host (" Offline build test: " + $(if($offlineSuccess){"PASSED"}else{"FAILED"})) -ForegroundColor $(if($offlineSuccess){"Green"}else{"Red"}) +Write-Host "" + +Write-Host "============================================================" -ForegroundColor Yellow +Write-Host " Usage in Air-gapped Environment" -ForegroundColor Yellow +Write-Host "============================================================" -ForegroundColor Yellow +Write-Host "" +Write-Host "Option 1: Use unpack script" -ForegroundColor White +Write-Host " .\unpack_and_offline_build_airgap.ps1" -ForegroundColor Gray +Write-Host "" +Write-Host "Option 2: Manual extraction" -ForegroundColor White +Write-Host " tar -xzf .tar.gz" -ForegroundColor Gray +Write-Host " cd " -ForegroundColor Gray +Write-Host " .\run_offline_build.ps1" -ForegroundColor Gray +Write-Host "" +Write-Host "Option 3: Direct commands" -ForegroundColor White +Write-Host ' $env:GRADLE_USER_HOME = ".\\_offline_gradle_home"' -ForegroundColor Gray +Write-Host " .\gradlew.bat --offline bootJar --no-daemon" -ForegroundColor Gray +Write-Host "" diff --git a/gradle/win/scripts/unpack_and_offline_build_airgap.ps1 b/gradle/win/scripts/unpack_and_offline_build_airgap.ps1 new file mode 100755 index 00000000..9342a2fe --- /dev/null +++ b/gradle/win/scripts/unpack_and_offline_build_airgap.ps1 @@ -0,0 +1,355 @@ +# unpack_and_offline_build_airgap.ps1 +# ============================================================================ +# Execution Environment: OFFLINE (Air-gapped, No Internet) +# Purpose: Extract bundle and run offline build +# ============================================================================ +# Windows PowerShell Only +# Version: 3.1 +# +# IMPORTANT: This script automatically: +# 1. Extracts the archive +# 2. Sets GRADLE_USER_HOME to project local cache +# 3. Configures settings.gradle for offline resolution +# 4. Runs build with --offline flag +# ============================================================================ + +$ErrorActionPreference = "Stop" +$ProgressPreference = "SilentlyContinue" + +# ============================================================================ +# Configuration +# ============================================================================ +$WRAPPER_SEED_PATH = "wrapper_jar_seed" +$OFFLINE_HOME_NAME = "_offline_gradle_home" + +Write-Host "" +Write-Host "============================================================" -ForegroundColor Cyan +Write-Host " Gradle Offline Build Runner" -ForegroundColor Cyan +Write-Host " Environment: AIR-GAPPED (No Internet)" -ForegroundColor Cyan +Write-Host " Mode: Fully Offline (--offline enforced)" -ForegroundColor Cyan +Write-Host "============================================================" -ForegroundColor Cyan +Write-Host "" + +# ============================================================================ +# [1/16] Check Current Directory +# ============================================================================ +Write-Host "==[1/16] Check Current Directory ==" -ForegroundColor Yellow +$Start = (Get-Location).Path +Write-Host ("PWD: " + $Start) +Write-Host "" + +# ============================================================================ +# [2/16] Select Archive +# ============================================================================ +Write-Host "==[2/16] Select Archive ==" -ForegroundColor Yellow + +$Archive = $null +if ($args.Count -ge 1) { + $Archive = $args[0].Trim().Trim('"').Trim("'") +} + +if ([string]::IsNullOrWhiteSpace($Archive)) { + $candidates = Get-ChildItem -Path $Start -File -ErrorAction SilentlyContinue | + Where-Object { $_.Name -match "\.(tar\.gz|tgz)$" } | + Sort-Object LastWriteTime -Descending + + if (-not $candidates -or $candidates.Count -eq 0) { + Write-Host "[ERROR] No archive found" -ForegroundColor Red + Get-ChildItem -Path $Start -File | Format-Table Name, Length -AutoSize + throw "ERROR: No .tar.gz file found" + } + + $Archive = $candidates[0].FullName + Write-Host ("[AUTO] " + (Split-Path $Archive -Leaf)) -ForegroundColor Cyan +} else { + if (-not [System.IO.Path]::IsPathRooted($Archive)) { + $Archive = Join-Path $Start $Archive + } + Write-Host ("[USER] " + (Split-Path $Archive -Leaf)) -ForegroundColor Cyan +} + +if (-not (Test-Path -LiteralPath $Archive)) { + throw "ERROR: Archive not found: $Archive" +} + +$archiveSizeMB = [math]::Round((Get-Item -LiteralPath $Archive).Length / 1MB, 2) +Write-Host ("Size: " + $archiveSizeMB + " MB") +Write-Host "" + +# ============================================================================ +# [3/16] Check tar.exe +# ============================================================================ +Write-Host "==[3/16] Check tar.exe ==" -ForegroundColor Yellow + +$tar = Get-Command tar.exe -ErrorAction SilentlyContinue +if (-not $tar) { throw "ERROR: tar.exe not found" } +Write-Host "[OK] tar.exe found" -ForegroundColor Green +Write-Host "" + +# ============================================================================ +# [4/16] Extract Archive +# ============================================================================ +Write-Host "==[4/16] Extract Archive ==" -ForegroundColor Yellow +Write-Host "[INFO] Extracting..." -ForegroundColor Gray + +& tar.exe -xzf $Archive -C $Start +if ($LASTEXITCODE -ne 0) { throw "ERROR: Extraction failed" } +Write-Host "[OK] Extracted" -ForegroundColor Green +Write-Host "" + +# ============================================================================ +# [5/16] Unblock Files +# ============================================================================ +Write-Host "==[5/16] Unblock Files ==" -ForegroundColor Yellow + +try { + Get-ChildItem -Path $Start -Recurse -Force -ErrorAction SilentlyContinue | + Unblock-File -ErrorAction SilentlyContinue + Write-Host "[OK] Files unblocked" -ForegroundColor Green +} catch { + Write-Host "[WARN] Unblock failed" -ForegroundColor DarkYellow +} +Write-Host "" + +# ============================================================================ +# [6/16] Find Project Root +# ============================================================================ +Write-Host "==[6/16] Find Project Root ==" -ForegroundColor Yellow + +$gradlewList = Get-ChildItem -Path $Start -Recurse -Filter "gradlew.bat" -File -ErrorAction SilentlyContinue +if (-not $gradlewList) { throw "ERROR: gradlew.bat not found" } + +$gradlew = $gradlewList | Sort-Object { $_.FullName.Length } | Select-Object -First 1 +$ProjectDir = $gradlew.Directory.FullName + +Write-Host ("Project: " + $ProjectDir) -ForegroundColor Cyan +Set-Location -LiteralPath $ProjectDir +Write-Host "" + +# ============================================================================ +# [7/16] Fix Permissions +# ============================================================================ +Write-Host "==[7/16] Fix Permissions ==" -ForegroundColor Yellow + +try { + $currentUser = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name + cmd /c "icacls `"$ProjectDir`" /grant `"$currentUser`:(OI)(CI)F`" /t /q" 2>&1 | Out-Null + Write-Host "[OK] Permissions fixed" -ForegroundColor Green +} catch { + Write-Host "[WARN] icacls failed" -ForegroundColor DarkYellow +} +Write-Host "" + +# ============================================================================ +# [8/16] Verify Wrapper +# ============================================================================ +Write-Host "==[8/16] Verify Wrapper ==" -ForegroundColor Yellow + +$WrapperDir = Join-Path $ProjectDir "gradle\wrapper" +$WrapperJar = Join-Path $WrapperDir "gradle-wrapper.jar" +$WrapperProp = Join-Path $WrapperDir "gradle-wrapper.properties" + +if (!(Test-Path -LiteralPath $WrapperProp)) { + throw "ERROR: gradle-wrapper.properties missing" +} + +if (!(Test-Path -LiteralPath $WrapperJar)) { + $SeedJar = Join-Path $ProjectDir "$WRAPPER_SEED_PATH\gradle-wrapper.jar" + if (Test-Path -LiteralPath $SeedJar) { + New-Item -ItemType Directory -Force -Path $WrapperDir | Out-Null + Copy-Item -Force -LiteralPath $SeedJar -Destination $WrapperJar + Write-Host "[OK] Injected from seed" -ForegroundColor Green + } else { + throw "ERROR: wrapper jar missing" + } +} else { + Write-Host "[OK] Wrapper verified" -ForegroundColor Green +} +Write-Host "" + +# ============================================================================ +# [9/16] Set GRADLE_USER_HOME +# ============================================================================ +Write-Host "==[9/16] Set GRADLE_USER_HOME ==" -ForegroundColor Yellow + +$OfflineHome = Join-Path $ProjectDir $OFFLINE_HOME_NAME +if (!(Test-Path -LiteralPath $OfflineHome)) { + throw "ERROR: _offline_gradle_home not found in archive" +} + +$env:GRADLE_USER_HOME = $OfflineHome +Write-Host ("GRADLE_USER_HOME = " + $env:GRADLE_USER_HOME) -ForegroundColor Cyan + +# Check cache +$CachesDir = Join-Path $OfflineHome "caches" +if (Test-Path -LiteralPath $CachesDir) { + $cacheSize = (Get-ChildItem -Path $CachesDir -Recurse -File -ErrorAction SilentlyContinue | + Measure-Object -Property Length -Sum).Sum + $cacheSizeMB = [math]::Round($cacheSize / 1MB, 2) + Write-Host ("[INFO] Cache size: " + $cacheSizeMB + " MB") -ForegroundColor Cyan +} else { + Write-Host "[WARN] No cache folder found" -ForegroundColor DarkYellow +} +Write-Host "" + +# ============================================================================ +# [10/16] Verify settings.gradle +# ============================================================================ +Write-Host "==[10/16] Verify settings.gradle ==" -ForegroundColor Yellow + +$settingsFile = $null +if (Test-Path -LiteralPath ".\settings.gradle") { $settingsFile = "settings.gradle" } +elseif (Test-Path -LiteralPath ".\settings.gradle.kts") { $settingsFile = "settings.gradle.kts" } + +if ($settingsFile) { + $content = Get-Content -LiteralPath ".\$settingsFile" -Raw + if ($content -match "mavenLocal\(\)" -and $content -match "pluginManagement") { + Write-Host "[OK] settings.gradle configured for offline" -ForegroundColor Green + } else { + Write-Host "[WARN] settings.gradle may not be configured for offline" -ForegroundColor DarkYellow + Write-Host "[INFO] Build may fail if plugins not cached" -ForegroundColor Gray + } +} +Write-Host "" + +# ============================================================================ +# [11/16] Test Gradle +# ============================================================================ +Write-Host "==[11/16] Test Gradle ==" -ForegroundColor Yellow + +$gradleWorks = $false +try { + $output = cmd /c ".\gradlew.bat --offline --version 2>&1" + if ($LASTEXITCODE -eq 0) { + $gradleWorks = $true + Write-Host "[OK] Gradle working in offline mode" -ForegroundColor Green + } +} catch { } + +if (-not $gradleWorks) { + Write-Host "[WARN] Gradle --version failed" -ForegroundColor DarkYellow +} +Write-Host "" + +# ============================================================================ +# [12/16] Stop Daemon +# ============================================================================ +Write-Host "==[12/16] Stop Daemon ==" -ForegroundColor Yellow + +try { cmd /c ".\gradlew.bat --stop 2>&1" | Out-Null } catch { } +Start-Sleep -Seconds 2 +Write-Host "[OK] Daemon stopped" -ForegroundColor Green +Write-Host "" + +# ============================================================================ +# [13/16] Run Offline Build +# ============================================================================ +Write-Host "==[13/16] Run Offline Build ==" -ForegroundColor Yellow +Write-Host "" +Write-Host "============================================================" -ForegroundColor Cyan +Write-Host " Building with --offline flag" -ForegroundColor Cyan +Write-Host " All dependencies from local cache" -ForegroundColor Cyan +Write-Host "============================================================" -ForegroundColor Cyan +Write-Host "" + +$buildSuccess = $false +$buildTask = $null + +# Try bootJar +Write-Host "[TRY] --offline bootJar..." -ForegroundColor Gray +try { + cmd /c ".\gradlew.bat --offline clean bootJar --no-daemon" + if ($LASTEXITCODE -eq 0) { + $buildSuccess = $true + $buildTask = "bootJar" + } +} catch { } + +# Try jar +if (-not $buildSuccess) { + Write-Host "[TRY] --offline jar..." -ForegroundColor Gray + try { + cmd /c ".\gradlew.bat --offline clean jar --no-daemon" + if ($LASTEXITCODE -eq 0) { + $buildSuccess = $true + $buildTask = "jar" + } + } catch { } +} + +# Try build +if (-not $buildSuccess) { + Write-Host "[TRY] --offline build..." -ForegroundColor Gray + try { + cmd /c ".\gradlew.bat --offline build --no-daemon" + if ($LASTEXITCODE -eq 0) { + $buildSuccess = $true + $buildTask = "build" + } + } catch { } +} + +Write-Host "" +if ($buildSuccess) { + Write-Host "============================================================" -ForegroundColor Green + Write-Host (" BUILD SUCCESS! (task: " + $buildTask + ")") -ForegroundColor Green + Write-Host "============================================================" -ForegroundColor Green +} else { + Write-Host "============================================================" -ForegroundColor Red + Write-Host " BUILD FAILED!" -ForegroundColor Red + Write-Host "============================================================" -ForegroundColor Red + Write-Host "" + Write-Host "Possible causes:" -ForegroundColor Yellow + Write-Host " - Dependencies not in cache" -ForegroundColor White + Write-Host " - Plugin resolution failed" -ForegroundColor White + Write-Host " - Need complete build in online env first" -ForegroundColor White + throw "Build failed" +} +Write-Host "" + +# ============================================================================ +# [14/16] Show Build Output +# ============================================================================ +Write-Host "==[14/16] Build Output ==" -ForegroundColor Yellow + +$libsDir = Join-Path $ProjectDir "build\libs" +if (Test-Path -LiteralPath $libsDir) { + Write-Host "build/libs contents:" -ForegroundColor Cyan + Get-ChildItem -LiteralPath $libsDir | + Format-Table Name, @{L="Size(KB)";E={[math]::Round($_.Length/1KB,1)}} -AutoSize | + Out-Host + + $mainJar = Get-ChildItem -LiteralPath $libsDir -Filter "*.jar" | + Where-Object { $_.Name -notmatch "plain|sources|javadoc" } | + Select-Object -First 1 +} else { + Write-Host "[WARN] build/libs not found" -ForegroundColor DarkYellow +} +Write-Host "" + +# ============================================================================ +# [15/16] Run Instructions +# ============================================================================ +Write-Host "==[15/16] Run Instructions ==" -ForegroundColor Yellow +Write-Host "" + +if ($mainJar) { + Write-Host "To run the application:" -ForegroundColor Cyan + Write-Host (" java -jar build\libs\" + $mainJar.Name) -ForegroundColor White + Write-Host "" +} + +Write-Host "To rebuild:" -ForegroundColor Cyan +Write-Host ' $env:GRADLE_USER_HOME = ".\\_offline_gradle_home"' -ForegroundColor White +Write-Host " .\gradlew.bat --offline bootJar --no-daemon" -ForegroundColor White +Write-Host "" + +# ============================================================================ +# [16/16] Complete +# ============================================================================ +Write-Host "============================================================" -ForegroundColor Green +Write-Host " Offline Build Complete!" -ForegroundColor Green +Write-Host "============================================================" -ForegroundColor Green +Write-Host "" +Write-Host ("Project: " + $ProjectDir) -ForegroundColor Cyan +Write-Host "" diff --git a/src/main/java/com/kamco/cd/kamcoback/common/api/HelloApiController.java b/src/main/java/com/kamco/cd/kamcoback/common/api/HelloApiController.java index 7353c2ce..c836b1fc 100644 --- a/src/main/java/com/kamco/cd/kamcoback/common/api/HelloApiController.java +++ b/src/main/java/com/kamco/cd/kamcoback/common/api/HelloApiController.java @@ -3,15 +3,22 @@ package com.kamco.cd.kamcoback.common.api; import com.kamco.cd.kamcoback.common.api.HelloDto.Res; import com.kamco.cd.kamcoback.common.service.ExternalJarRunner; import com.kamco.cd.kamcoback.common.service.HelloService; -import io.swagger.v3.oas.annotations.Hidden; +import com.kamco.cd.kamcoback.config.resttemplate.ExternalHttpClient; +import com.kamco.cd.kamcoback.config.resttemplate.ExternalHttpClient.ExternalCallResult; import io.swagger.v3.oas.annotations.Parameter; +import java.util.List; import lombok.RequiredArgsConstructor; +import lombok.extern.log4j.Log4j2; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; -@Hidden +@Log4j2 @RequiredArgsConstructor @RestController @RequestMapping("/api/hello") @@ -19,6 +26,7 @@ public class HelloApiController { private final HelloService helloService; private final ExternalJarRunner externalJarRunner; + private final ExternalHttpClient externalHttpClient; @GetMapping public HelloDto.Res hello(HelloDto.Req req) { @@ -40,4 +48,24 @@ public class HelloApiController { String mapIds) { externalJarRunner.run(jarPath, batchIds, inferenceId, mapIds); } + + @GetMapping("/batch/{batchId}") + public String batch(@PathVariable String batchId) { + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + headers.setAccept(List.of(MediaType.APPLICATION_JSON)); + String url = "http://10.100.0.11:8000/batches" + "/" + batchId; + ExternalCallResult result = + externalHttpClient.call(url, HttpMethod.GET, null, headers, String.class); + + int status = result.statusCode(); + if (status == 404) { + log.info("Batch not found. batchId={}", batchId); + return null; + } + if (status < 200 || status >= 300) { + return null; + } + return result.toString(); + } } diff --git a/src/main/java/com/kamco/cd/kamcoback/common/service/ExternalJarRunner.java b/src/main/java/com/kamco/cd/kamcoback/common/service/ExternalJarRunner.java index 20f5db1d..06835b2e 100644 --- a/src/main/java/com/kamco/cd/kamcoback/common/service/ExternalJarRunner.java +++ b/src/main/java/com/kamco/cd/kamcoback/common/service/ExternalJarRunner.java @@ -13,7 +13,7 @@ import org.springframework.stereotype.Component; @Component public class ExternalJarRunner { - private static final long TIMEOUT_MINUTES = 30; + private static final long TIMEOUT_MINUTES = TimeUnit.DAYS.toMinutes(3); /** * shp 파일 생성 diff --git a/src/main/java/com/kamco/cd/kamcoback/inference/InferenceResultShpApiController.java b/src/main/java/com/kamco/cd/kamcoback/inference/InferenceResultShpApiController.java index a431bcb1..d5b4cfbb 100644 --- a/src/main/java/com/kamco/cd/kamcoback/inference/InferenceResultShpApiController.java +++ b/src/main/java/com/kamco/cd/kamcoback/inference/InferenceResultShpApiController.java @@ -13,6 +13,7 @@ import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @Tag(name = "추론결과 데이터 생성", description = "추론결과 데이터 생성 API") @@ -42,4 +43,15 @@ public class InferenceResultShpApiController { @PathVariable Long learnId) { return ApiResponseDto.createOK(inferenceResultShpService.saveInferenceResultData(learnId)); } + + @Operation(summary = "추론결과 shp 생성", description = "추론결과 shp 생성") + @PostMapping("/shp/{uid}") + public ApiResponseDto createShp( + @PathVariable String uid, + @RequestParam Long m1BatchId, + @RequestParam Long m2BatchId, + @RequestParam Long m3BatchId) { + inferenceResultShpService.createShp(uid, m1BatchId, m2BatchId, m3BatchId); + return ApiResponseDto.createOK(null); + } } diff --git a/src/main/java/com/kamco/cd/kamcoback/inference/dto/InferenceDetailDto.java b/src/main/java/com/kamco/cd/kamcoback/inference/dto/InferenceDetailDto.java index 513d59f5..1a358bd2 100644 --- a/src/main/java/com/kamco/cd/kamcoback/inference/dto/InferenceDetailDto.java +++ b/src/main/java/com/kamco/cd/kamcoback/inference/dto/InferenceDetailDto.java @@ -304,6 +304,7 @@ public class InferenceDetailDto { Double classAfterProb; Long mapSheetNum; String mapSheetName; + String subUid; // @JsonIgnore String gemoStr; // @JsonIgnore String geomCenterStr; @@ -321,7 +322,8 @@ public class InferenceDetailDto { String classAfterCd, Double classAfterProb, Long mapSheetNum, - String mapSheetName) { + String mapSheetName, + String subUid) { this.uuid = uuid; this.uid = uid; this.compareYyyy = compareYyyy; @@ -335,6 +337,7 @@ public class InferenceDetailDto { this.classAfterProb = classAfterProb; this.mapSheetNum = mapSheetNum; this.mapSheetName = mapSheetName; + this.subUid = subUid; // this.gemoStr = gemoStr; // this.geomCenterStr = geomCenterStr; // @@ -440,6 +443,7 @@ public class InferenceDetailDto { @JsonFormatDttm private ZonedDateTime inferEndDttm; private Integer stage; private String elapsedDuration; + private String subUid; public AnalResultInfo( String analTitle, @@ -452,7 +456,8 @@ public class InferenceDetailDto { String mapSheetScope, ZonedDateTime inferStartDttm, ZonedDateTime inferEndDttm, - Integer stage) { + Integer stage, + String subUid) { this.analTitle = analTitle; this.modelVer1 = modelVer1; this.modelVer2 = modelVer2; @@ -464,6 +469,7 @@ public class InferenceDetailDto { this.inferStartDttm = inferStartDttm; this.inferEndDttm = inferEndDttm; this.stage = stage; + this.subUid = subUid; Duration elapsed = (inferStartDttm != null && inferEndDttm != null) ? Duration.between(inferStartDttm, inferEndDttm) diff --git a/src/main/java/com/kamco/cd/kamcoback/inference/dto/InferenceResultDto.java b/src/main/java/com/kamco/cd/kamcoback/inference/dto/InferenceResultDto.java index 2521c8c5..9c8f5f37 100644 --- a/src/main/java/com/kamco/cd/kamcoback/inference/dto/InferenceResultDto.java +++ b/src/main/java/com/kamco/cd/kamcoback/inference/dto/InferenceResultDto.java @@ -85,8 +85,8 @@ public class InferenceResultDto { public enum Status implements EnumType { READY("대기"), IN_PROGRESS("진행중"), - END("종료"), - ; + END("완료"), + FORCED_END("강제종료"); private final String desc; public static Status fromCode(String code) { diff --git a/src/main/java/com/kamco/cd/kamcoback/inference/dto/InferenceSendDto.java b/src/main/java/com/kamco/cd/kamcoback/inference/dto/InferenceSendDto.java index ab90238a..5f7ca4fc 100644 --- a/src/main/java/com/kamco/cd/kamcoback/inference/dto/InferenceSendDto.java +++ b/src/main/java/com/kamco/cd/kamcoback/inference/dto/InferenceSendDto.java @@ -4,12 +4,14 @@ import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; +import lombok.ToString; /** AI API 추론 실행 DTO */ @Getter @Setter @NoArgsConstructor @AllArgsConstructor +@ToString public class InferenceSendDto { private pred_requests_areas pred_requests_areas; @@ -25,6 +27,7 @@ public class InferenceSendDto { @Setter @AllArgsConstructor @NoArgsConstructor + @ToString public static class pred_requests_areas { private Integer input1_year; diff --git a/src/main/java/com/kamco/cd/kamcoback/inference/service/InferenceResultService.java b/src/main/java/com/kamco/cd/kamcoback/inference/service/InferenceResultService.java index 8e4d4fdf..d6bef76f 100644 --- a/src/main/java/com/kamco/cd/kamcoback/inference/service/InferenceResultService.java +++ b/src/main/java/com/kamco/cd/kamcoback/inference/service/InferenceResultService.java @@ -558,11 +558,11 @@ public class InferenceResultService { externalHttpClient.call(url, HttpMethod.DELETE, dto, headers, String.class); if (!result.success()) { - log.warn("Failed to delete inference result"); + throw new CustomApiException("BAD_GATEWAY", HttpStatus.BAD_GATEWAY); } SaveInferenceAiDto request = new SaveInferenceAiDto(); - request.setStatus(Status.END.getId()); + request.setStatus(Status.FORCED_END.getId()); request.setUuid(dto.getUuid()); request.setUpdateUid(userUtil.getId()); request.setInferEndDttm(ZonedDateTime.now()); diff --git a/src/main/java/com/kamco/cd/kamcoback/inference/service/InferenceResultShpService.java b/src/main/java/com/kamco/cd/kamcoback/inference/service/InferenceResultShpService.java index 6dd1fe36..db8c4b78 100644 --- a/src/main/java/com/kamco/cd/kamcoback/inference/service/InferenceResultShpService.java +++ b/src/main/java/com/kamco/cd/kamcoback/inference/service/InferenceResultShpService.java @@ -1,7 +1,12 @@ package com.kamco.cd.kamcoback.inference.service; import com.kamco.cd.kamcoback.inference.dto.InferenceResultShpDto; +import com.kamco.cd.kamcoback.inference.dto.InferenceResultsTestingDto; +import com.kamco.cd.kamcoback.postgres.core.InferenceResultCoreService; import com.kamco.cd.kamcoback.postgres.core.InferenceResultShpCoreService; +import com.kamco.cd.kamcoback.scheduler.service.ShpPipelineService; +import java.util.ArrayList; +import java.util.List; import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; @@ -13,13 +18,49 @@ import org.springframework.transaction.annotation.Transactional; public class InferenceResultShpService { private final InferenceResultShpCoreService coreService; + private final InferenceResultCoreService inferenceResultCoreService; + private final ShpPipelineService shpPipelineService; @Value("${mapsheet.shp.baseurl}") private String baseDir; + @Value("${inference.jar-path}") + private String jarPath; + + @Value("${file.dataset-dir}") + private String datasetDir; + /** inference_results 테이블을 기준으로 분석 결과 테이블과 도형 테이블을 최신 상태로 반영한다. */ @Transactional public InferenceResultShpDto.InferenceCntDto saveInferenceResultData(Long id) { return coreService.buildInferenceData(id); } + + public void createShp(String uid, Long m1BatchId, Long m2BatchId, Long m3BatchId) { + List batchIds = new ArrayList<>(); + batchIds.add(m1BatchId); + batchIds.add(m2BatchId); + batchIds.add(m3BatchId); + + List resultList = + inferenceResultCoreService.getInferenceResults(batchIds); + String inferenceId = ""; + StringBuilder sb = new StringBuilder(); + + for (InferenceResultsTestingDto.ShpDto dto : resultList) { + if (dto.getMapId() == null) { + continue; + } + if (!sb.isEmpty()) { + sb.append(","); + } + sb.append("\"").append(dto.getMapId()).append("\""); + } + inferenceId = uid; + String mapIds = sb.toString(); + String batchId = m1BatchId + "," + m2BatchId + "," + m3BatchId; + + // shp 파일 비동기 생성 + shpPipelineService.runPipeline(jarPath, datasetDir, batchId, inferenceId, mapIds); + } } diff --git a/src/main/java/com/kamco/cd/kamcoback/menu/MyMenuApiController.java b/src/main/java/com/kamco/cd/kamcoback/menu/MyMenuApiController.java index ade26a80..5a877f78 100644 --- a/src/main/java/com/kamco/cd/kamcoback/menu/MyMenuApiController.java +++ b/src/main/java/com/kamco/cd/kamcoback/menu/MyMenuApiController.java @@ -2,7 +2,6 @@ package com.kamco.cd.kamcoback.menu; import com.kamco.cd.kamcoback.common.utils.UserUtil; import com.kamco.cd.kamcoback.config.api.ApiResponseDto; -import com.kamco.cd.kamcoback.menu.dto.MenuDto; import com.kamco.cd.kamcoback.menu.dto.MyMenuDto; import com.kamco.cd.kamcoback.menu.service.MyMenuService; import io.swagger.v3.oas.annotations.Operation; @@ -26,18 +25,48 @@ public class MyMenuApiController { private final MyMenuService myMenuService; @Operation(summary = "사용자별 메뉴 조회", description = "로그인 사용자별 권한 메뉴 목록") - @ApiResponses( - value = { - @ApiResponse( - responseCode = "200", - description = "조회 성공", - content = - @Content( - mediaType = "application/json", - schema = @Schema(implementation = MenuDto.Basic.class))), - @ApiResponse(responseCode = "404", description = "코드를 찾을 수 없음", content = @Content), - @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) - }) + @ApiResponses({ + @ApiResponse( + responseCode = "200", + description = "조회 성공", + content = + @Content( + mediaType = "application/json", + schema = + @Schema( + type = "object", + example = + """ + { + "data": [ + { + "id": "string", + "name": "string", + "menuUrl": null, + "order": 0, + "children": [ + { + "id": "string", + "name": "string", + "menuUrl": "string", + "order": 0, + "children": [] + }, + { + "id": "string", + "name": "string", + "menuUrl": "string", + "order": 0, + "children": [] + } + ] + } + ] + } + """))), + @ApiResponse(responseCode = "404", description = "코드를 찾을 수 없음", content = @Content), + @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) + }) @GetMapping public ApiResponseDto> getFindAllByRole() { UserUtil userUtil = new UserUtil(); diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/Inference/InferenceResultRepositoryImpl.java b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/Inference/InferenceResultRepositoryImpl.java index 11f8f0f7..52171908 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/Inference/InferenceResultRepositoryImpl.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/Inference/InferenceResultRepositoryImpl.java @@ -212,8 +212,6 @@ public class InferenceResultRepositoryImpl implements InferenceResultRepositoryC AND r.map_id ~ '^[0-9]+$' AND r.map_id::bigint = msadi.map_sheet_num WHERE msl.anal_uid = :analUid - AND r.before_c is not null - AND r.before_p is not null AND r.after_c is not null AND r.after_p is not null ORDER BY r.uid, r.created_date DESC NULLS LAST @@ -279,8 +277,8 @@ public class InferenceResultRepositoryImpl implements InferenceResultRepositoryC INNER JOIN tb_map_sheet_anal_data_inference_geom msadig ON msadi.data_uid = msadig.data_uid WHERE msai.anal_uid = :analUid - AND msadig.class_before_cd IS NOT NULL AND msadig.class_after_cd IS NOT NULL + AND msadig.class_after_prob IS NOT NULL GROUP BY msadig.compare_yyyy ,msadig.target_yyyy diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/Inference/MapSheetLearnRepositoryImpl.java b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/Inference/MapSheetLearnRepositoryImpl.java index 56091dc9..cb43eadb 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/Inference/MapSheetLearnRepositoryImpl.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/Inference/MapSheetLearnRepositoryImpl.java @@ -311,7 +311,8 @@ public class MapSheetLearnRepositoryImpl implements MapSheetLearnRepositoryCusto mapSheetLearnEntity.mapSheetScope, mapSheetLearnEntity.inferStartDttm, mapSheetLearnEntity.inferEndDttm, - mapSheetLearnEntity.stage)) + mapSheetLearnEntity.stage, + Expressions.stringTemplate("substring({0} from 1 for 8)", mapSheetLearnEntity.uid))) .from(mapSheetLearnEntity) .leftJoin(m1) .on(mapSheetLearnEntity.m1ModelUuid.eq(m1.uuid)) @@ -426,7 +427,10 @@ public class MapSheetLearnRepositoryImpl implements MapSheetLearnRepositoryCusto mapSheetAnalDataInferenceGeomEntity.classAfterCd, mapSheetAnalDataInferenceGeomEntity.classAfterProb, mapSheetAnalDataInferenceGeomEntity.mapSheetNum, - mapInkx5kEntity.mapidNm)) + mapInkx5kEntity.mapidNm, + Expressions.stringTemplate( + "substring({0} from 1 for 8)", + mapSheetAnalDataInferenceGeomEntity.resultUid))) .from(mapSheetAnalInferenceEntity) .join(mapSheetAnalDataInferenceEntity) .on(mapSheetAnalDataInferenceEntity.analUid.eq(mapSheetAnalInferenceEntity.id)) diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/mapsheet/MapSheetMngRepositoryImpl.java b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/mapsheet/MapSheetMngRepositoryImpl.java index bea9dfce..d979e192 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/mapsheet/MapSheetMngRepositoryImpl.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/mapsheet/MapSheetMngRepositoryImpl.java @@ -7,6 +7,7 @@ import static com.kamco.cd.kamcoback.postgres.entity.QMapSheetMngHstEntity.mapSh import static com.kamco.cd.kamcoback.postgres.entity.QYearEntity.yearEntity; import static com.querydsl.core.types.dsl.Expressions.nullExpression; +import com.kamco.cd.kamcoback.common.enums.CommonUseStatus; import com.kamco.cd.kamcoback.common.geometry.GeoJsonFileWriter.ImageFeature; import com.kamco.cd.kamcoback.inference.dto.InferenceResultDto; import com.kamco.cd.kamcoback.inference.dto.InferenceResultDto.MapSheetScope; @@ -531,6 +532,12 @@ public class MapSheetMngRepositoryImpl extends QuerydslRepositorySupport nullExpression(Integer.class), nullExpression(Boolean.class))) .from(mapSheetMngHstEntity) + .innerJoin(mapInkx5kEntity) + .on( + mapInkx5kEntity + .mapidcdNo + .eq(mapSheetMngHstEntity.mapSheetNum) + .and(mapInkx5kEntity.useInference.eq(CommonUseStatus.USE))) .where(whereBuilder) .fetch(); } @@ -580,6 +587,8 @@ public class MapSheetMngRepositoryImpl extends QuerydslRepositorySupport ORDER BY x::int DESC LIMIT 1 ) s ON true + INNER JOIN tb_map_inkx_5k tmik + ON t.map_sheet_num = tmik.mapidcd_no AND tmik.use_inference = 'USE' WHERE t.map_sheet_num = ANY(:mapIds) """; diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/trainingdata/TrainingDataLabelRepositoryImpl.java b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/trainingdata/TrainingDataLabelRepositoryImpl.java index dbab47f3..712dc1d8 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/trainingdata/TrainingDataLabelRepositoryImpl.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/trainingdata/TrainingDataLabelRepositoryImpl.java @@ -591,6 +591,7 @@ public class TrainingDataLabelRepositoryImpl extends QuerydslRepositorySupport .afterCogUrl(afterCogUrl) .mapBox(mapBbox) .learnGeometries(learnDataList) // learnGeometry -> learnGeometries + .labelState(assignment.toDto().getWorkState()) .build(); } catch (Exception e) { diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/trainingdata/TrainingDataReviewRepositoryImpl.java b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/trainingdata/TrainingDataReviewRepositoryImpl.java index 84ebf43a..b1875485 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/trainingdata/TrainingDataReviewRepositoryImpl.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/trainingdata/TrainingDataReviewRepositoryImpl.java @@ -619,6 +619,7 @@ public class TrainingDataReviewRepositoryImpl extends QuerydslRepositorySupport .afterCogUrl(afterCogUrl) .mapBox(mapBbox) .learnGeometries(learnDataList) // learnGeometry -> learnGeometries + .inspectState(assignment.toDto().getInspectState()) .build(); } catch (Exception e) { diff --git a/src/main/java/com/kamco/cd/kamcoback/scheduler/service/MapSheetInferenceJobService.java b/src/main/java/com/kamco/cd/kamcoback/scheduler/service/MapSheetInferenceJobService.java index a61476b8..7192b10d 100644 --- a/src/main/java/com/kamco/cd/kamcoback/scheduler/service/MapSheetInferenceJobService.java +++ b/src/main/java/com/kamco/cd/kamcoback/scheduler/service/MapSheetInferenceJobService.java @@ -369,6 +369,7 @@ public class MapSheetInferenceJobService { m.setCd_model_type(inferenceType); m.setPriority(progressDto.getPriority()); + // log.info("InferenceSendDto={}", m); // 추론 실행 api 호출 Long batchId = ensureAccepted(m); @@ -414,11 +415,7 @@ public class MapSheetInferenceJobService { } // 1) 요청 로그 - try { - log.debug("Inference request dto={}", objectMapper.writeValueAsString(dto)); - } catch (JsonProcessingException e) { - log.warn("Failed to serialize inference dto", e); - } + log.info("Inference request dto={}", dto); // 2) local 환경 임시 처리 if ("local".equals(profile)) { diff --git a/src/main/java/com/kamco/cd/kamcoback/scheduler/service/ShpPipelineService.java b/src/main/java/com/kamco/cd/kamcoback/scheduler/service/ShpPipelineService.java index f15f96e0..1f5c0970 100644 --- a/src/main/java/com/kamco/cd/kamcoback/scheduler/service/ShpPipelineService.java +++ b/src/main/java/com/kamco/cd/kamcoback/scheduler/service/ShpPipelineService.java @@ -26,16 +26,17 @@ public class ShpPipelineService { } try { - // 1 uid 기준 도엽별 shp, geojson 파일 생성 - externalJarRunner.run(jarPath, batchId, inferenceId, mapIds); - - // 2 uid 기준 merge shp, geojson 파일 생성 + // uid 기준 merge shp, geojson 파일 생성 externalJarRunner.run(jarPath, batchId, inferenceId, ""); - // 3 uid 기준 shp 파일 geoserver 등록 + // uid 기준 shp 파일 geoserver 등록 String register = datasetDir + "/" + inferenceId + "/merge/" + inferenceId + ".shp"; externalJarRunner.run(jarPath, register, inferenceId); + // uid 기준 도엽별 shp, geojson 파일 생성 + // TODO 도엽별은 속도 확인 후 다시 체크 + // externalJarRunner.run(jarPath, batchId, inferenceId, mapIds); + log.info("SHP pipeline finished. inferenceId={}", inferenceId); } catch (Exception e) { diff --git a/src/main/java/com/kamco/cd/kamcoback/trainingdata/TrainingDataLabelApiController.java b/src/main/java/com/kamco/cd/kamcoback/trainingdata/TrainingDataLabelApiController.java index a7a59600..4139bccc 100644 --- a/src/main/java/com/kamco/cd/kamcoback/trainingdata/TrainingDataLabelApiController.java +++ b/src/main/java/com/kamco/cd/kamcoback/trainingdata/TrainingDataLabelApiController.java @@ -333,8 +333,6 @@ public class TrainingDataLabelApiController { trainingDataLabelService.getDefaultPagingNumber(userId, size, assignmentUid)); } - // 이번 범위에서는 새로운 폴리곤 추가하지 않는다고 하여 Hidden - @Hidden @Operation( summary = "새로운 polygon(들) 추가 저장", description = "탐지결과 외 새로운 polygon을 추가로 저장합니다. 단일 또는 여러 개를 저장할 수 있습니다.") diff --git a/src/main/java/com/kamco/cd/kamcoback/trainingdata/TrainingDataReviewApiController.java b/src/main/java/com/kamco/cd/kamcoback/trainingdata/TrainingDataReviewApiController.java index bb593969..bf9318b5 100644 --- a/src/main/java/com/kamco/cd/kamcoback/trainingdata/TrainingDataReviewApiController.java +++ b/src/main/java/com/kamco/cd/kamcoback/trainingdata/TrainingDataReviewApiController.java @@ -335,8 +335,6 @@ public class TrainingDataReviewApiController { trainingDataReviewService.getDefaultPagingNumber(userId, size, operatorUid)); } - // 이번 범위에서는 새로운 폴리곤 추가하지 않는다고 하여 Hidden - @Hidden @Operation( summary = "새로운 polygon(들) 추가 저장", description = "탐지결과 외 새로운 polygon을 추가로 저장합니다. 단일 또는 여러 개를 저장할 수 있습니다.") diff --git a/src/main/java/com/kamco/cd/kamcoback/trainingdata/dto/TrainingDataLabelDto.java b/src/main/java/com/kamco/cd/kamcoback/trainingdata/dto/TrainingDataLabelDto.java index 1e2628b0..65cdbb36 100644 --- a/src/main/java/com/kamco/cd/kamcoback/trainingdata/dto/TrainingDataLabelDto.java +++ b/src/main/java/com/kamco/cd/kamcoback/trainingdata/dto/TrainingDataLabelDto.java @@ -326,6 +326,9 @@ public class TrainingDataLabelDto { @Schema(description = "라벨링 툴에서 그린 폴리곤들 (여러 개 가능)") private List learnGeometries; + + @Schema(description = "라벨 상태") + private String labelState; } @Schema(name = "ChangeDetectionInfo", description = "변화탐지정보") diff --git a/src/main/java/com/kamco/cd/kamcoback/trainingdata/dto/TrainingDataReviewDto.java b/src/main/java/com/kamco/cd/kamcoback/trainingdata/dto/TrainingDataReviewDto.java index 87ac558e..d3026009 100644 --- a/src/main/java/com/kamco/cd/kamcoback/trainingdata/dto/TrainingDataReviewDto.java +++ b/src/main/java/com/kamco/cd/kamcoback/trainingdata/dto/TrainingDataReviewDto.java @@ -319,6 +319,9 @@ public class TrainingDataReviewDto { @Schema(description = "검수 시 추가/수정한 폴리곤들 (여러 개 가능)") private List learnGeometries; + + @Schema(description = "검수 상태") + private String inspectState; } @Schema(name = "ChangeDetectionInfo", description = "변화탐지정보")