From a3c9a37b3c5c06a23262d89da1b76acfa0f504fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A4=80=ED=98=81?= <127603139+HYH0804@users.noreply.github.com> Date: Wed, 27 May 2026 21:58:33 +0900 Subject: [PATCH 01/29] =?UTF-8?q?#250=20[Fix]=20=ED=88=AC=ED=91=9C=20?= =?UTF-8?q?=EB=B9=84=EC=9C=A8=20=EA=B3=84=EC=82=B0=20=EA=B8=B0=EC=A4=80?= =?UTF-8?q?=EC=9D=84=20preVoteOption=EC=97=90=EC=84=9C=20postVoteOption?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=20=EC=88=98=EC=A0=95=20(#252)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## #️⃣ 연관된 이슈 - #250 ## 📝 작업 내용 ### ♻️ Refactor | 내용 | 파일 | |------|------| | 불필요한 import 제거 | `UserService.java` | | 투표 비율 계산 기준을 preVoteOption → postVoteOption으로 수정 | `BattleVoteServiceImpl.java` | | totalCount도 사후 투표 완료된 건만 카운트하도록 수정 | `BattleVoteServiceImpl.java` | | countByBattleAndPostVoteOption, countByBattleAndPostVoteOptionIsNotNull 메서드 추가 | `BattleVoteServiceImpl.java` | ## 📌 공유 사항 > ▎ 1. 기존 코드에서 투표 비율(%)이 preVoteOption 기준으로 계산되어 사전 투표만 한 유저도 카운트에 포함되고 있었습니다. ▎ 2. 사후 투표(postVoteOption)가 완료된 건만 기준으로 비율을 계산하도록 수정했습니다. ## ✅ 체크리스트 - [x] Reviewer에 팀원들을 선택했나요? - [x] Assignees에 본인을 선택했나요? - [x] 컨벤션에 맞는 Type을 선택했나요? - [x] Development에 이슈를 연동했나요? - [x] Merge 하려는 브랜치가 올바르게 설정되어 있나요? - [x] 컨벤션을 지키고 있나요? - [x] 로컬에서 실행했을 때 에러가 발생하지 않나요? - [x] 팀원들에게 PR 링크 공유를 했나요? ## 📸 스크린샷 ## 💬 리뷰 요구사항 > 1. Co-authored-by: Claude Sonnet 4.6 --- .../picke/domain/vote/repository/BattleVoteRepository.java | 4 ++++ .../swyp/picke/domain/vote/service/BattleVoteServiceImpl.java | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/swyp/picke/domain/vote/repository/BattleVoteRepository.java b/src/main/java/com/swyp/picke/domain/vote/repository/BattleVoteRepository.java index 825ddcd4..07bbf0bb 100644 --- a/src/main/java/com/swyp/picke/domain/vote/repository/BattleVoteRepository.java +++ b/src/main/java/com/swyp/picke/domain/vote/repository/BattleVoteRepository.java @@ -27,6 +27,10 @@ public interface BattleVoteRepository extends JpaRepository { long countByBattleAndPreVoteOption(Battle battle, BattleOption preVoteOption); + long countByBattleAndPostVoteOption(Battle battle, BattleOption postVoteOption); + + long countByBattleAndPostVoteOptionIsNotNull(Battle battle); + Optional findTopByBattleOrderByUpdatedAtDesc(Battle battle); @Query("SELECT v FROM BattleVote v JOIN FETCH v.battle JOIN FETCH v.preVoteOption " + diff --git a/src/main/java/com/swyp/picke/domain/vote/service/BattleVoteServiceImpl.java b/src/main/java/com/swyp/picke/domain/vote/service/BattleVoteServiceImpl.java index 6f62f008..1b13289d 100644 --- a/src/main/java/com/swyp/picke/domain/vote/service/BattleVoteServiceImpl.java +++ b/src/main/java/com/swyp/picke/domain/vote/service/BattleVoteServiceImpl.java @@ -75,11 +75,11 @@ public Long findPostVoteOptionId(Long battleId, Long userId) { public VoteStatsResponse getVoteStats(Long battleId) { Battle battle = battleService.findById(battleId); List options = battleOptionRepository.findByBattle(battle); - long totalCount = battleVoteRepository.countByBattle(battle); + long totalCount = battleVoteRepository.countByBattleAndPostVoteOptionIsNotNull(battle); List stats = options.stream() .map(option -> { - long count = battleVoteRepository.countByBattleAndPreVoteOption(battle, option); + long count = battleVoteRepository.countByBattleAndPostVoteOption(battle, option); double ratio = totalCount > 0 ? Math.round((double) count / totalCount * 1000.0) / 10.0 : 0.0; From a38c141e0f0c0c350f466d6adce1fd38b7aac614 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A4=80=ED=98=81?= <127603139+HYH0804@users.noreply.github.com> Date: Wed, 3 Jun 2026 20:29:13 +0900 Subject: [PATCH 02/29] =?UTF-8?q?#254=20[Refactor]=20=EA=B4=80=EC=A0=90=20?= =?UTF-8?q?=EB=93=B1=EB=A1=9D/=EC=88=98=EC=A0=95=20=EC=8B=9C=20GPT=20?= =?UTF-8?q?=EA=B2=80=EC=88=98=20=EC=BD=94=EB=93=9C=20=EC=A0=9C=EA=B1=B0=20?= =?UTF-8?q?(#256)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## #️ 연관된 이슈 - #254 ## 📝 작업 내용 ### ♻️ Refactor | 내용 | 파일 | |------|------| | 관점 등록/수정 시 GPT 검수 주석 코드 제거 | `PerspectiveService.java` | ## 📌 공유 사항 > 1. 기존에 `createPerspective()`, `updatePerspective()`에서 GPT 검수 호출이 주석 처리된 채 남아있던 dead code를 제거했습니다. 동작 방식은 동일하게 등록/수정 즉시 `PUBLISHED` 상태로 저장됩니다. ## ✅ 체크리스트 - [x] Reviewer에 팀원들을 선택했나요? - [x] Assignees에 본인을 선택했나요? - [x] 컨벤션에 맞는 Type을 선택했나요? - [x] Development에 이슈를 연동했나요? - [x] Merge 하려는 브랜치가 올바르게 설정되어 있나요? - [x] 컨벤션을 지키고 있나요? - [x] 로컬에서 실행했을 때 에러가 발생하지 않나요? - [x] 팀원들에게 PR 링크 공유를 했나요? ## 📸 스크린샷 해당 없음 (코드 정리 작업) ## 💬 리뷰 요구사항 > 1. 없습니다. Co-authored-by: Claude Sonnet 4.6 --- .../picke/domain/perspective/service/PerspectiveService.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/main/java/com/swyp/picke/domain/perspective/service/PerspectiveService.java b/src/main/java/com/swyp/picke/domain/perspective/service/PerspectiveService.java index 72e80b52..b45defd2 100644 --- a/src/main/java/com/swyp/picke/domain/perspective/service/PerspectiveService.java +++ b/src/main/java/com/swyp/picke/domain/perspective/service/PerspectiveService.java @@ -92,10 +92,8 @@ public CreatePerspectiveResponse createPerspective(Long battleId, Long userId, C .content(request.content()) .build(); - // 댓글 검수 비활성화 및 댓글 작성 승인 perspective.updateStatus(PerspectiveStatus.PUBLISHED); Perspective saved = perspectiveRepository.save(perspective); - // gptModerationService.moderate(saved.getId(), saved.getContent()); return new CreatePerspectiveResponse(saved.getId(), saved.getStatus(), saved.getCreatedAt()); } @@ -163,9 +161,7 @@ public UpdatePerspectiveResponse updatePerspective(Long perspectiveId, Long user Perspective perspective = findPerspectiveById(perspectiveId); validateOwnership(perspective, userId); perspective.updateContent(request.content()); - // 댓글 검수 미수행 및 댓글 바로 적용 perspective.updateStatus(PerspectiveStatus.PUBLISHED); - // gptModerationService.moderate(perspective.getId(), perspective.getContent()); return new UpdatePerspectiveResponse(perspective.getId(), perspective.getContent(), perspective.getUpdatedAt()); } From cee2c5d0ba9bf3252166d9ecbe608cecf61d299b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A4=80=ED=98=81?= <127603139+HYH0804@users.noreply.github.com> Date: Wed, 3 Jun 2026 20:55:31 +0900 Subject: [PATCH 03/29] =?UTF-8?q?#255=20[Refactor]=20VoteStatsResponse=20O?= =?UTF-8?q?ptionStat=EC=97=90=20title=20=ED=95=84=EB=93=9C=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=20(#257)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## #️ 연관된 이슈 - #255 ## 📝 작업 내용 ### ♻️ Refactor | 내용 | 파일 | |------|------| | VoteStatsResponse OptionStat에 title 필드 추가 | `VoteStatsResponse.java`, `BattleVoteServiceImpl.java` | ## 📌 공유 사항 > 1. `GET /api/v1/battles/{battleId}/vote-stats` 응답의 `OptionStat`에 `title` 필드가 추가되었습니다. 옵션 이름(ex. "변기는 변기다")을 투표 % 바 및 관점 탭 구성에 활용해 주세요. > 2. 관점 목록 조회 시 옵션 탭 필터는 `optionId` 파라미터로 전달하면 됩니다. (`GET /api/v1/battles/{battleId}/perspectives?optionId={optionId}`) ## ✅ 체크리스트 - [x] Reviewer에 팀원들을 선택했나요? - [x] Assignees에 본인을 선택했나요? - [x] 컨벤션에 맞는 Type을 선택했나요? - [x] Development에 이슈를 연동했나요? - [x] Merge 하려는 브랜치가 올바르게 설정되어 있나요? - [x] 컨벤션을 지키고 있나요? - [x] 로컬에서 실행했을 때 에러가 발생하지 않나요? - [x] 팀원들에게 PR 링크 공유를 했나요? ## 📸 스크린샷 해당 없음 (응답 필드 추가) ## 💬 리뷰 요구사항 > 1. 없습니다. Co-authored-by: Claude Sonnet 4.6 --- .../swyp/picke/domain/vote/dto/response/VoteStatsResponse.java | 1 + .../swyp/picke/domain/vote/service/BattleVoteServiceImpl.java | 1 + 2 files changed, 2 insertions(+) diff --git a/src/main/java/com/swyp/picke/domain/vote/dto/response/VoteStatsResponse.java b/src/main/java/com/swyp/picke/domain/vote/dto/response/VoteStatsResponse.java index 1537c1a6..ab859860 100644 --- a/src/main/java/com/swyp/picke/domain/vote/dto/response/VoteStatsResponse.java +++ b/src/main/java/com/swyp/picke/domain/vote/dto/response/VoteStatsResponse.java @@ -10,6 +10,7 @@ public record VoteStatsResponse( ) { public record OptionStat( Long optionId, + String title, String imageUrl, long voteCount, double ratio diff --git a/src/main/java/com/swyp/picke/domain/vote/service/BattleVoteServiceImpl.java b/src/main/java/com/swyp/picke/domain/vote/service/BattleVoteServiceImpl.java index 1b13289d..d4461436 100644 --- a/src/main/java/com/swyp/picke/domain/vote/service/BattleVoteServiceImpl.java +++ b/src/main/java/com/swyp/picke/domain/vote/service/BattleVoteServiceImpl.java @@ -85,6 +85,7 @@ public VoteStatsResponse getVoteStats(Long battleId) { : 0.0; return new VoteStatsResponse.OptionStat( option.getId(), + option.getTitle(), urlProvider.getImageUrl(FileCategory.PHILOSOPHER, option.getImageUrl()), count, ratio From 53533b8e8d5f408bc04094ec0b9e2b26963e091c Mon Sep 17 00:00:00 2001 From: Youwol <153346797+si-zero@users.noreply.github.com> Date: Wed, 3 Jun 2026 23:12:52 +0900 Subject: [PATCH 04/29] =?UTF-8?q?#258=20[Feat]=20=EC=B6=9C=EC=84=9D?= =?UTF-8?q?=EC=B2=B4=ED=81=AC=20API=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/api-specs/attendance-api.md | 360 ++++++++++++++++++ docs/erd/attendence.puml | 61 +++ .../controller/AdminAttendanceController.java | 49 +++ .../response/AdminAttendanceResponse.java | 49 +++ .../admin/service/AdminAttendanceService.java | 125 ++++++ .../controller/AttendanceController.java | 41 ++ .../dto/response/AttendanceResponse.java | 46 +++ .../attendance/entity/AttendanceRecord.java | 53 +++ .../attendance/entity/AttendanceStreak.java | 85 +++++ .../attendance/enums/AttendanceStatus.java | 7 + .../AttendanceRecordRepository.java | 30 ++ .../AttendanceStreakRepository.java | 11 + .../AttendanceWeeklyResetScheduler.java | 46 +++ .../attendance/service/AttendanceService.java | 204 ++++++++++ .../picke/domain/user/enums/CreditType.java | 1 + .../domain/user/service/CreditService.java | 7 + .../global/common/exception/ErrorCode.java | 5 +- .../picke/global/config/SwaggerConfig.java | 6 +- 18 files changed, 1184 insertions(+), 2 deletions(-) create mode 100644 docs/api-specs/attendance-api.md create mode 100644 docs/erd/attendence.puml create mode 100644 src/main/java/com/swyp/picke/domain/admin/controller/AdminAttendanceController.java create mode 100644 src/main/java/com/swyp/picke/domain/admin/dto/attendance/response/AdminAttendanceResponse.java create mode 100644 src/main/java/com/swyp/picke/domain/admin/service/AdminAttendanceService.java create mode 100644 src/main/java/com/swyp/picke/domain/attendance/controller/AttendanceController.java create mode 100644 src/main/java/com/swyp/picke/domain/attendance/dto/response/AttendanceResponse.java create mode 100644 src/main/java/com/swyp/picke/domain/attendance/entity/AttendanceRecord.java create mode 100644 src/main/java/com/swyp/picke/domain/attendance/entity/AttendanceStreak.java create mode 100644 src/main/java/com/swyp/picke/domain/attendance/enums/AttendanceStatus.java create mode 100644 src/main/java/com/swyp/picke/domain/attendance/repository/AttendanceRecordRepository.java create mode 100644 src/main/java/com/swyp/picke/domain/attendance/repository/AttendanceStreakRepository.java create mode 100644 src/main/java/com/swyp/picke/domain/attendance/scheduler/AttendanceWeeklyResetScheduler.java create mode 100644 src/main/java/com/swyp/picke/domain/attendance/service/AttendanceService.java diff --git a/docs/api-specs/attendance-api.md b/docs/api-specs/attendance-api.md new file mode 100644 index 00000000..a7ceb84c --- /dev/null +++ b/docs/api-specs/attendance-api.md @@ -0,0 +1,360 @@ +# 출석체크 API 명세서 + +## 1. 설계 메모 + +- 출석체크 API는 `snake_case` 필드명을 기준으로 합니다. +- 출석 주기는 **월요일 기준 1주일(월~일)**로 초기화됩니다. +- 매일 1회 출석 체크 시 `+5P`를 지급하고, 7일 연속 출석 달성 시 추가로 `+7P`를 지급합니다. +- 7일 연속 출석 실패 시 다음 주 월요일에 연속 출석 카운트가 초기화됩니다. +- 인증이 필요한 모든 API는 `Authorization: Bearer {access_token}` 헤더를 요구합니다. +- 외부 응답에서는 내부 PK인 `user_id`를 노출하지 않고 `user_tag`를 사용합니다. +- 포인트 단위는 `P(포인트)`이며, 지급 내역은 별도 이력 테이블에 저장합니다. + +### 1.1 출석 상태 정의 + +| 상태 값 | 설명 | +|---------|------| +| `ATTENDED` | 해당 요일 출석 완료 | +| `NOT_ATTENDED` | 해당 요일 미출석 (오늘 이후 포함) | +| `PENDING` | 오늘 날짜이며 아직 출석 전 | + +### 1.2 출석 보상 정책 + +| 조건 | 지급 포인트 | +|------|-------------| +| 매일 출석 체크 | `+5P` | +| 7일 연속 출석 달성 (일요일) | 추가 `+7P` | + +### 1.3 연속 출석 초기화 정책 + +- 연속 출석 카운트는 **매주 월요일 00:00**에 초기화됩니다. +- 한 주(월~일) 내에 출석하지 않은 날이 있어도, 해당 주 일요일까지는 연속 출석 달성이 가능합니다. +- 단, 전날 출석 없이 오늘 출석 시 연속 카운트는 1로 리셋됩니다. + +--- + +## 2. 출석체크 API + +### 2.1 `POST /api/v1/attendance/check` + +오늘의 출석을 체크하고 포인트를 지급합니다. + +- 하루에 1회만 출석 가능합니다. 중복 출석 시 `409`를 반환합니다. +- 출석 성공 시 `+5P`를 즉시 지급합니다. +- 7일 연속 출석 달성 시 `+5P`에 추가로 `+7P`를 지급합니다. + +요청 헤더: + +- `Authorization: Bearer {access_token}` + +응답: + +```json +{ + "statusCode": 200, + "data": { + "user_tag": "pique-5010f67e", + "attended_at": "2025-07-10T09:00:00Z", + "points_earned": 5, + "streak_bonus_earned": false, + "streak_bonus_points": 0, + "consecutive_days": 4, + "total_points": 125 + }, + "error": null +} +``` + +7일 연속 출석 달성 시 응답: + +```json +{ + "statusCode": 200, + "data": { + "user_tag": "pique-5010f67e", + "attended_at": "2025-07-13T09:00:00Z", + "points_earned": 5, + "streak_bonus_earned": true, + "streak_bonus_points": 7, + "consecutive_days": 7, + "total_points": 167 + }, + "error": null +} +``` + +--- + +### 2.2 `GET /api/v1/attendance/weekly` + +이번 주(월~일) 출석 현황 및 연속 출석 정보를 조회합니다. + +- 요일별 출석 상태와 현재 연속 출석 일수를 반환합니다. +- 현재 주의 월요일 기준으로 데이터를 반환합니다. + +요청 헤더: + +- `Authorization: Bearer {access_token}` + +응답: + +```json +{ + "statusCode": 200, + "data": { + "user_tag": "pique-5010f67e", + "week_start_date": "2025-07-07", + "consecutive_days": 4, + "is_streak_achieved": false, + "weekly_attendance": [ + { "day": "MON", "date": "2025-07-07", "status": "ATTENDED", "points": 5 }, + { "day": "TUE", "date": "2025-07-08", "status": "ATTENDED", "points": 5 }, + { "day": "WED", "date": "2025-07-09", "status": "ATTENDED", "points": 5 }, + { "day": "THU", "date": "2025-07-10", "status": "ATTENDED", "points": 5 }, + { "day": "FRI", "date": "2025-07-11", "status": "PENDING", "points": 0 }, + { "day": "SAT", "date": "2025-07-12", "status": "NOT_ATTENDED", "points": 0 }, + { "day": "SUN", "date": "2025-07-13", "status": "NOT_ATTENDED", "points": 0 } + ], + "streak_reward_points": 7 + }, + "error": null +} +``` + +--- + +### 2.3 `GET /api/v1/attendance/summary` + +사용자의 전체 출석 통계 및 누적 포인트를 조회합니다. + +- 총 출석 일수, 최장 연속 출석 일수, 현재 연속 출석 일수, 총 획득 포인트를 반환합니다. + +요청 헤더: + +- `Authorization: Bearer {access_token}` + +응답: + +```json +{ + "statusCode": 200, + "data": { + "user_tag": "pique-5010f67e", + "total_attended_days": 32, + "current_consecutive_days": 4, + "max_consecutive_days": 14, + "total_points_from_attendance": 185, + "last_attended_at": "2025-07-10T09:00:00Z" + }, + "error": null +} +``` + +--- + +### 2.4 `GET /api/v1/attendance/points/history` + +출석 포인트 지급 이력을 조회합니다. + +- 최신순으로 반환하며, 페이지네이션을 지원합니다. + +요청 헤더: + +- `Authorization: Bearer {access_token}` + +쿼리 파라미터: + +| 파라미터 | 타입 | 필수 | 설명 | +|----------|------|------|------| +| `page` | `integer` | N | 페이지 번호 (기본값: `1`) | +| `size` | `integer` | N | 페이지 크기 (기본값: `20`, 최대: `50`) | + +응답: + +```json +{ + "statusCode": 200, + "data": { + "total_count": 32, + "page": 1, + "size": 20, + "items": [ + { + "rewarded_at": "2025-07-10T09:00:00Z", + "points": 5, + "reason": "DAILY_ATTENDANCE", + "consecutive_days": 4 + }, + { + "rewarded_at": "2025-07-06T08:30:00Z", + "points": 7, + "reason": "STREAK_BONUS", + "consecutive_days": 7 + } + ] + }, + "error": null +} +``` + +가능한 `reason` 값: + +- `DAILY_ATTENDANCE` — 일일 출석 보상 (`+5P`) +- `STREAK_BONUS` — 7일 연속 출석 달성 보상 (`+7P`) + +--- + +## 3. 어드민 API + +- 어드민 전용 API는 `Authorization: Bearer {access_token}` 헤더와 함께 어드민 권한이 있는 계정만 호출 가능합니다. +- 어드민 권한이 없는 계정이 호출 시 `403`과 `FORBIDDEN`을 반환합니다. + +### 3.1 `GET /api/v1/admin/attendance/stats` + +전체 유저의 출석 현황을 집계하여 반환합니다. + +- 일별 출석자 수, 전체 출석률 등 서비스 운영 지표를 제공합니다. +- `from` ~ `to` 범위를 지정하지 않으면 최근 7일 기준으로 반환합니다. +- `from` ~ `to` 최대 조회 범위는 90일입니다. + +요청 헤더: + +- `Authorization: Bearer {access_token}` + +쿼리 파라미터: + +| 파라미터 | 타입 | 필수 | 설명 | +|----------|------|------|------| +| `from` | `string` | N | 조회 시작일 (`YYYY-MM-DD`, 기본값: 7일 전) | +| `to` | `string` | N | 조회 종료일 (`YYYY-MM-DD`, 기본값: 오늘) | + +응답: + +```json +{ + "statusCode": 200, + "data": { + "from": "2025-07-04", + "to": "2025-07-10", + "total_users": 1500, + "daily_stats": [ + { + "date": "2025-07-04", + "attended_count": 832, + "attendance_rate": 55.5 + }, + { + "date": "2025-07-05", + "attended_count": 910, + "attendance_rate": 60.7 + }, + { + "date": "2025-07-06", + "attended_count": 765, + "attendance_rate": 51.0 + }, + { + "date": "2025-07-07", + "attended_count": 1020, + "attendance_rate": 68.0 + }, + { + "date": "2025-07-08", + "attended_count": 998, + "attendance_rate": 66.5 + }, + { + "date": "2025-07-09", + "attended_count": 1043, + "attendance_rate": 69.5 + }, + { + "date": "2025-07-10", + "attended_count": 874, + "attendance_rate": 58.3 + } + ] + }, + "error": null +} +``` + +--- + +### 3.2 `GET /api/v1/admin/attendance/users/{user_tag}` + +특정 유저의 출석 이력 및 통계를 조회합니다. + +- 해당 유저의 전체 출석 통계와 날짜별 출석 이력을 반환합니다. +- 이력은 최신순으로 반환하며, 페이지네이션을 지원합니다. + +요청 헤더: + +- `Authorization: Bearer {access_token}` + +경로 파라미터: + +| 파라미터 | 타입 | 필수 | 설명 | +|----------|------|------|------| +| `user_tag` | `string` | Y | 조회할 유저의 `user_tag` | + +쿼리 파라미터: + +| 파라미터 | 타입 | 필수 | 설명 | +|----------|------|------|------| +| `page` | `integer` | N | 페이지 번호 (기본값: `1`) | +| `size` | `integer` | N | 페이지 크기 (기본값: `20`, 최대: `50`) | + +응답: + +```json +{ + "statusCode": 200, + "data": { + "user_tag": "pique-5010f67e", + "summary": { + "total_attended_days": 32, + "current_consecutive_days": 4, + "max_consecutive_days": 14, + "total_points_from_attendance": 185, + "last_attended_at": "2025-07-10T09:00:00Z" + }, + "total_count": 32, + "page": 1, + "size": 20, + "items": [ + { + "attended_at": "2025-07-10T09:00:00Z", + "consecutive_days": 4, + "points_earned": 5, + "streak_bonus_earned": false + }, + { + "attended_at": "2025-07-09T08:45:00Z", + "consecutive_days": 3, + "points_earned": 5, + "streak_bonus_earned": false + } + ] + }, + "error": null +} +``` + +--- + +## 4. 에러 코드 + +### 4.1 출석체크 관련 에러 코드 + +| HTTP | 에러 코드 | 설명 | +|------|-----------|------| +| `400` | `COMMON_INVALID_PARAMETER` | 요청 파라미터가 잘못되었습니다. | +| `401` | `AUTH_ACCESS_TOKEN_EXPIRED` | Access Token 만료 — Refresh 필요 | +| `401` | `AUTH_REFRESH_TOKEN_EXPIRED` | Refresh Token 만료 — 재로그인 필요 | +| `403` | `FORBIDDEN` | 어드민 권한이 없는 사용자 | +| `403` | `USER_BANNED` | 영구 제재된 사용자 | +| `403` | `USER_SUSPENDED` | 일정 기간 이용 정지된 사용자 | +| `404` | `USER_NOT_FOUND` | 존재하지 않는 `user_tag` | +| `409` | `ATTENDANCE_ALREADY_CHECKED` | 오늘 이미 출석체크를 완료했습니다. | +| `500` | `INTERNAL_SERVER_ERROR` | 서버 오류 | \ No newline at end of file diff --git a/docs/erd/attendence.puml b/docs/erd/attendence.puml new file mode 100644 index 00000000..b4c4f266 --- /dev/null +++ b/docs/erd/attendence.puml @@ -0,0 +1,61 @@ +@startuml +hide circle +hide methods +skinparam linetype ortho + +entity "ATTENDANCE_RECORDS\n일별 출석 기록" as attendance_records { + * id : BIGINT <> + -- + user_id : BIGINT <> + attended_date : DATE + points_earned : INT + created_at : TIMESTAMP +} + +entity "ATTENDANCE_STREAKS\n연속 출석 상태" as attendance_streaks { + * user_id : BIGINT <> + -- + current_streak : INT + max_streak : INT + streak_week_start : DATE + is_streak_achieved : BOOLEAN + updated_at : TIMESTAMP +} + +entity "ATTENDANCE_POINT_HISTORIES\n출석 포인트 지급 이력" as attendance_point_histories { + * id : BIGINT <> + -- + user_id : BIGINT <> + points : INT + reason : ENUM('DAILY_ATTENDANCE', 'STREAK_BONUS') + consecutive_days : INT + created_at : TIMESTAMP +} + +attendance_records -[hidden]down- attendance_streaks +attendance_streaks -[hidden]down- attendance_point_histories + +USERS ||--o{ attendance_records : "" +USERS ||--|| attendance_streaks : "" +USERS ||--o{ attendance_point_histories : "" + +note right of attendance_records + (user_id, attended_date) UNIQUE 제약으로 + 하루 1회 출석만 허용한다. +end note + +note right of attendance_streaks + user_id 가 PK 이므로 유저당 1개 row 유지. + 매주 월요일 00:00 에 current_streak 과 + is_streak_achieved 를 초기화한다. + streak_week_start 는 해당 주 월요일 날짜. +end note + +note bottom of attendance_point_histories + reason 값 + - DAILY_ATTENDANCE : 일일 출석 보상 (+5P) + - STREAK_BONUS : 7일 연속 달성 보상 (+7P) + consecutive_days 는 지급 시점의 연속 출석 일수. +end note + +@enduml \ No newline at end of file diff --git a/src/main/java/com/swyp/picke/domain/admin/controller/AdminAttendanceController.java b/src/main/java/com/swyp/picke/domain/admin/controller/AdminAttendanceController.java new file mode 100644 index 00000000..e00ef3b6 --- /dev/null +++ b/src/main/java/com/swyp/picke/domain/admin/controller/AdminAttendanceController.java @@ -0,0 +1,49 @@ +package com.swyp.picke.domain.admin.controller; + +import com.swyp.picke.domain.admin.dto.attendance.response.AdminAttendanceResponse.StatsResponse; +import com.swyp.picke.domain.admin.dto.attendance.response.AdminAttendanceResponse.UserAttendanceResponse; +import com.swyp.picke.domain.admin.service.AdminAttendanceService; +import com.swyp.picke.global.common.response.ApiResponse; +import io.swagger.v3.oas.annotations.Hidden; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; +import org.springframework.format.annotation.DateTimeFormat; +import org.springframework.security.access.prepost.PreAuthorize; +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; + +import java.time.LocalDate; + +@Hidden +@Tag(name = "관리자 출석체크 API", description = "출석 현황 집계 및 특정 유저 출석 이력 조회") +@RestController +@RequestMapping("/api/v1/admin/attendance") +@RequiredArgsConstructor +@PreAuthorize("hasRole('ADMIN')") +public class AdminAttendanceController { + + private final AdminAttendanceService adminAttendanceService; + + @Operation(summary = "전체 출석 현황 집계", description = "일별 출석자 수, 출석률을 집계합니다. 기본 최근 7일, 최대 90일.") + @GetMapping("/stats") + public ApiResponse getStats( + @RequestParam(required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate from, + @RequestParam(required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate to + ) { + return ApiResponse.onSuccess(adminAttendanceService.getStats(from, to)); + } + + @Operation(summary = "특정 유저 출석 이력 조회", description = "user_tag로 특정 유저의 출석 통계 및 이력을 조회합니다.") + @GetMapping("/users/{userTag}") + public ApiResponse getUserAttendance( + @PathVariable String userTag, + @RequestParam(defaultValue = "1") int page, + @RequestParam(defaultValue = "20") int size + ) { + return ApiResponse.onSuccess(adminAttendanceService.getUserAttendance(userTag, page, size)); + } +} diff --git a/src/main/java/com/swyp/picke/domain/admin/dto/attendance/response/AdminAttendanceResponse.java b/src/main/java/com/swyp/picke/domain/admin/dto/attendance/response/AdminAttendanceResponse.java new file mode 100644 index 00000000..9739c5e0 --- /dev/null +++ b/src/main/java/com/swyp/picke/domain/admin/dto/attendance/response/AdminAttendanceResponse.java @@ -0,0 +1,49 @@ +package com.swyp.picke.domain.admin.dto.attendance.response; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.List; + +public class AdminAttendanceResponse { + + // GET /api/v1/admin/attendance/stats + public record StatsResponse( + LocalDate from, + LocalDate to, + @JsonProperty("total_users") long totalUsers, + @JsonProperty("daily_stats") List dailyStats + ) { + public record DailyStat( + LocalDate date, + @JsonProperty("attended_count") long attendedCount, + @JsonProperty("attendance_rate") double attendanceRate + ) {} + } + + // GET /api/v1/admin/attendance/users/{user_tag} + public record UserAttendanceResponse( + @JsonProperty("user_tag") String userTag, + AttendanceSummary summary, + @JsonProperty("total_count") long totalCount, + int page, + int size, + List items + ) { + public record AttendanceSummary( + @JsonProperty("total_attended_days") long totalAttendedDays, + @JsonProperty("current_consecutive_days") int currentConsecutiveDays, + @JsonProperty("max_consecutive_days") int maxConsecutiveDays, + @JsonProperty("total_points_from_attendance") int totalPointsFromAttendance, + @JsonProperty("last_attended_at") LocalDateTime lastAttendedAt + ) {} + + public record AttendanceItem( + @JsonProperty("attended_at") LocalDateTime attendedAt, + @JsonProperty("consecutive_days") int consecutiveDays, + @JsonProperty("points_earned") int pointsEarned, + @JsonProperty("streak_bonus_earned") boolean streakBonusEarned + ) {} + } +} diff --git a/src/main/java/com/swyp/picke/domain/admin/service/AdminAttendanceService.java b/src/main/java/com/swyp/picke/domain/admin/service/AdminAttendanceService.java new file mode 100644 index 00000000..c4d1f13c --- /dev/null +++ b/src/main/java/com/swyp/picke/domain/admin/service/AdminAttendanceService.java @@ -0,0 +1,125 @@ +package com.swyp.picke.domain.admin.service; + +import com.swyp.picke.domain.admin.dto.attendance.response.AdminAttendanceResponse.StatsResponse; +import com.swyp.picke.domain.admin.dto.attendance.response.AdminAttendanceResponse.StatsResponse.DailyStat; +import com.swyp.picke.domain.admin.dto.attendance.response.AdminAttendanceResponse.UserAttendanceResponse; +import com.swyp.picke.domain.admin.dto.attendance.response.AdminAttendanceResponse.UserAttendanceResponse.AttendanceItem; +import com.swyp.picke.domain.admin.dto.attendance.response.AdminAttendanceResponse.UserAttendanceResponse.AttendanceSummary; +import com.swyp.picke.domain.attendance.entity.AttendanceRecord; +import com.swyp.picke.domain.attendance.entity.AttendanceStreak; +import com.swyp.picke.domain.attendance.repository.AttendanceRecordRepository; +import com.swyp.picke.domain.attendance.repository.AttendanceStreakRepository; +import com.swyp.picke.domain.user.entity.User; +import com.swyp.picke.domain.user.repository.UserRepository; +import com.swyp.picke.domain.user.service.CreditService; +import com.swyp.picke.domain.user.service.UserService; +import com.swyp.picke.global.common.exception.CustomException; +import com.swyp.picke.global.common.exception.ErrorCode; +import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Service +@RequiredArgsConstructor +@Transactional(readOnly = true) +public class AdminAttendanceService { + + private static final ZoneId SEOUL_ZONE = ZoneId.of("Asia/Seoul"); + private static final int MAX_DATE_RANGE_DAYS = 90; + + private final AttendanceRecordRepository attendanceRecordRepository; + private final AttendanceStreakRepository attendanceStreakRepository; + private final UserRepository userRepository; + private final UserService userService; + private final CreditService creditService; + + public StatsResponse getStats(LocalDate from, LocalDate to) { + LocalDate today = LocalDate.now(SEOUL_ZONE); + + if (from == null) from = today.minusDays(6); + if (to == null) to = today; + + if (from.isAfter(to) || to.minusDays(MAX_DATE_RANGE_DAYS).isAfter(from)) { + throw new CustomException(ErrorCode.COMMON_INVALID_PARAMETER); + } + + long totalUsers = userRepository.count(); + + List rawStats = attendanceRecordRepository.countAttendanceGroupByDate(from, to); + Map countMap = new HashMap<>(); + for (Object[] row : rawStats) { + countMap.put((LocalDate) row[0], (Long) row[1]); + } + + List dailyStats = new ArrayList<>(); + LocalDate cursor = from; + while (!cursor.isAfter(to)) { + long attendedCount = countMap.getOrDefault(cursor, 0L); + double rate = totalUsers > 0 + ? Math.round((attendedCount * 1000.0 / totalUsers)) / 10.0 + : 0.0; + dailyStats.add(new DailyStat(cursor, attendedCount, rate)); + cursor = cursor.plusDays(1); + } + + return new StatsResponse(from, to, totalUsers, dailyStats); + } + + public UserAttendanceResponse getUserAttendance(String userTag, int page, int size) { + User user = userService.findByUserTag(userTag); + + long totalAttendedDays = attendanceRecordRepository.countByUserId(user.getId()); + + AttendanceStreak streak = attendanceStreakRepository.findByUserId(user.getId()).orElse(null); + int currentStreak = streak != null ? streak.getCurrentStreak() : 0; + int maxStreak = streak != null ? streak.getMaxStreak() : 0; + + int totalPoints = creditService.getTotalPoints(user.getId()); + + LocalDateTime lastAttendedAt = attendanceRecordRepository + .findTopByUserIdOrderByAttendedDateDesc(user.getId()) + .map(r -> r.getAttendedDate().atStartOfDay()) + .orElse(null); + + AttendanceSummary summary = new AttendanceSummary( + totalAttendedDays, + currentStreak, + maxStreak, + totalPoints, + lastAttendedAt + ); + + Pageable pageable = PageRequest.of(page - 1, size, Sort.by(Sort.Direction.DESC, "attendedDate")); + Page recordPage = attendanceRecordRepository.findByUserId(user.getId(), pageable); + + List items = recordPage.getContent().stream() + .map(r -> new AttendanceItem( + r.getAttendedDate().atStartOfDay(), + 0, + r.getPointsEarned(), + false + )) + .toList(); + + return new UserAttendanceResponse( + user.getUserTag(), + summary, + recordPage.getTotalElements(), + page, + size, + items + ); + } +} diff --git a/src/main/java/com/swyp/picke/domain/attendance/controller/AttendanceController.java b/src/main/java/com/swyp/picke/domain/attendance/controller/AttendanceController.java new file mode 100644 index 00000000..a176cae9 --- /dev/null +++ b/src/main/java/com/swyp/picke/domain/attendance/controller/AttendanceController.java @@ -0,0 +1,41 @@ +package com.swyp.picke.domain.attendance.controller; + +import com.swyp.picke.domain.attendance.dto.response.AttendanceResponse.CheckResponse; +import com.swyp.picke.domain.attendance.dto.response.AttendanceResponse.SummaryResponse; +import com.swyp.picke.domain.attendance.dto.response.AttendanceResponse.WeeklyResponse; +import com.swyp.picke.domain.attendance.service.AttendanceService; +import com.swyp.picke.global.common.response.ApiResponse; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/api/v1/attendance") +@Tag(name = "출석체크 API", description = "출석 체크, 주간 현황 조회, 통계 조회") +public class AttendanceController { + + private final AttendanceService attendanceService; + + @Operation(summary = "출석 체크", description = "오늘의 출석을 체크하고 포인트를 지급합니다. 하루 1회만 가능합니다.") + @PostMapping("/check") + public ApiResponse check() { + return ApiResponse.onSuccess(attendanceService.check()); + } + + @Operation(summary = "이번 주 출석 현황 조회", description = "이번 주(월~일) 요일별 출석 상태와 연속 출석 정보를 조회합니다.") + @GetMapping("/weekly") + public ApiResponse getWeekly() { + return ApiResponse.onSuccess(attendanceService.getWeekly()); + } + + @Operation(summary = "출석 통계 조회", description = "총 출석 일수, 연속 출석 일수, 누적 포인트 등 전체 통계를 조회합니다.") + @GetMapping("/summary") + public ApiResponse getSummary() { + return ApiResponse.onSuccess(attendanceService.getSummary()); + } +} diff --git a/src/main/java/com/swyp/picke/domain/attendance/dto/response/AttendanceResponse.java b/src/main/java/com/swyp/picke/domain/attendance/dto/response/AttendanceResponse.java new file mode 100644 index 00000000..e00fa9d1 --- /dev/null +++ b/src/main/java/com/swyp/picke/domain/attendance/dto/response/AttendanceResponse.java @@ -0,0 +1,46 @@ +package com.swyp.picke.domain.attendance.dto.response; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.swyp.picke.domain.attendance.enums.AttendanceStatus; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.List; + +public class AttendanceResponse { + + public record CheckResponse( + @JsonProperty("user_tag") String userTag, + @JsonProperty("attended_at") LocalDateTime attendedAt, + @JsonProperty("points_earned") int pointsEarned, + @JsonProperty("streak_bonus_earned") boolean streakBonusEarned, + @JsonProperty("streak_bonus_points") int streakBonusPoints, + @JsonProperty("consecutive_days") int consecutiveDays, + @JsonProperty("total_points") int totalPoints + ) {} + + public record WeeklyResponse( + @JsonProperty("user_tag") String userTag, + @JsonProperty("week_start_date") LocalDate weekStartDate, + @JsonProperty("consecutive_days") int consecutiveDays, + @JsonProperty("is_streak_achieved") boolean isStreakAchieved, + @JsonProperty("weekly_attendance") List weeklyAttendance, + @JsonProperty("streak_reward_points") int streakRewardPoints + ) { + public record DayAttendance( + String day, + LocalDate date, + AttendanceStatus status, + int points + ) {} + } + + public record SummaryResponse( + @JsonProperty("user_tag") String userTag, + @JsonProperty("total_attended_days") long totalAttendedDays, + @JsonProperty("current_consecutive_days") int currentConsecutiveDays, + @JsonProperty("max_consecutive_days") int maxConsecutiveDays, + @JsonProperty("total_points_from_attendance") int totalPointsFromAttendance, + @JsonProperty("last_attended_at") LocalDateTime lastAttendedAt + ) {} +} diff --git a/src/main/java/com/swyp/picke/domain/attendance/entity/AttendanceRecord.java b/src/main/java/com/swyp/picke/domain/attendance/entity/AttendanceRecord.java new file mode 100644 index 00000000..6085412d --- /dev/null +++ b/src/main/java/com/swyp/picke/domain/attendance/entity/AttendanceRecord.java @@ -0,0 +1,53 @@ +package com.swyp.picke.domain.attendance.entity; + +import com.swyp.picke.domain.user.entity.User; +import com.swyp.picke.global.common.BaseEntity; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.Index; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Table; +import jakarta.persistence.UniqueConstraint; +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.time.LocalDate; + +@Getter +@Entity +@Table( + name = "attendance_records", + uniqueConstraints = { + @UniqueConstraint( + name = "uq_attendance_user_date", + columnNames = {"user_id", "attended_date"} + ) + }, + indexes = { + @Index(name = "idx_attendance_record_user_id", columnList = "user_id") + } +) +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class AttendanceRecord extends BaseEntity { + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "user_id", nullable = false) + private User user; + + @Column(name = "attended_date", nullable = false) + private LocalDate attendedDate; + + @Column(name = "points_earned", nullable = false) + private int pointsEarned; + + @Builder + private AttendanceRecord(User user, LocalDate attendedDate, int pointsEarned) { + this.user = user; + this.attendedDate = attendedDate; + this.pointsEarned = pointsEarned; + } +} diff --git a/src/main/java/com/swyp/picke/domain/attendance/entity/AttendanceStreak.java b/src/main/java/com/swyp/picke/domain/attendance/entity/AttendanceStreak.java new file mode 100644 index 00000000..a03d5508 --- /dev/null +++ b/src/main/java/com/swyp/picke/domain/attendance/entity/AttendanceStreak.java @@ -0,0 +1,85 @@ +package com.swyp.picke.domain.attendance.entity; + +import com.swyp.picke.domain.user.entity.User; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.MapsId; +import jakarta.persistence.OneToOne; +import jakarta.persistence.Table; +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.time.LocalDate; +import java.time.LocalDateTime; + +@Getter +@Entity +@Table(name = "attendance_streaks") +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class AttendanceStreak { + + @Id + @Column(name = "user_id") + private Long userId; + + @MapsId + @OneToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "user_id") + private User user; + + @Column(name = "current_streak", nullable = false) + private int currentStreak; + + @Column(name = "max_streak", nullable = false) + private int maxStreak; + + @Column(name = "streak_week_start", nullable = false) + private LocalDate streakWeekStart; + + @Column(name = "is_streak_achieved", nullable = false) + private boolean isStreakAchieved; + + @Column(name = "updated_at", nullable = false) + private LocalDateTime updatedAt; + + @Builder + private AttendanceStreak(User user, int currentStreak, int maxStreak, + LocalDate streakWeekStart, boolean isStreakAchieved) { + this.user = user; + this.currentStreak = currentStreak; + this.maxStreak = maxStreak; + this.streakWeekStart = streakWeekStart; + this.isStreakAchieved = isStreakAchieved; + this.updatedAt = LocalDateTime.now(); + } + + public void attend(LocalDate today) { + this.currentStreak++; + if (this.currentStreak > this.maxStreak) { + this.maxStreak = this.currentStreak; + } + if (this.currentStreak >= 7) { + this.isStreakAchieved = true; + } + this.updatedAt = LocalDateTime.now(); + } + + public void resetStreak(LocalDate weekStart) { + this.currentStreak = 1; + this.streakWeekStart = weekStart; + this.isStreakAchieved = false; + this.updatedAt = LocalDateTime.now(); + } + + public void initWeek(LocalDate weekStart) { + this.currentStreak = 0; + this.streakWeekStart = weekStart; + this.isStreakAchieved = false; + this.updatedAt = LocalDateTime.now(); + } +} diff --git a/src/main/java/com/swyp/picke/domain/attendance/enums/AttendanceStatus.java b/src/main/java/com/swyp/picke/domain/attendance/enums/AttendanceStatus.java new file mode 100644 index 00000000..d9485560 --- /dev/null +++ b/src/main/java/com/swyp/picke/domain/attendance/enums/AttendanceStatus.java @@ -0,0 +1,7 @@ +package com.swyp.picke.domain.attendance.enums; + +public enum AttendanceStatus { + ATTENDED, // 해당 요일 출석 완료 + NOT_ATTENDED, // 해당 요일 미출석 (오늘 이후 포함) + PENDING // 오늘 날짜이며 아직 출석 전 +} diff --git a/src/main/java/com/swyp/picke/domain/attendance/repository/AttendanceRecordRepository.java b/src/main/java/com/swyp/picke/domain/attendance/repository/AttendanceRecordRepository.java new file mode 100644 index 00000000..748e5166 --- /dev/null +++ b/src/main/java/com/swyp/picke/domain/attendance/repository/AttendanceRecordRepository.java @@ -0,0 +1,30 @@ +package com.swyp.picke.domain.attendance.repository; + +import com.swyp.picke.domain.attendance.entity.AttendanceRecord; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +import java.time.LocalDate; +import java.util.List; +import java.util.Optional; + +public interface AttendanceRecordRepository extends JpaRepository { + + boolean existsByUserIdAndAttendedDate(Long userId, LocalDate attendedDate); + + List findByUserIdAndAttendedDateBetween(Long userId, LocalDate from, LocalDate to); + + Page findByUserId(Long userId, Pageable pageable); + + long countByUserId(Long userId); + + Optional findTopByUserIdOrderByAttendedDateDesc(Long userId); + + @Query("SELECT ar.attendedDate, COUNT(DISTINCT ar.user.id) FROM AttendanceRecord ar " + + "WHERE ar.attendedDate BETWEEN :from AND :to " + + "GROUP BY ar.attendedDate ORDER BY ar.attendedDate") + List countAttendanceGroupByDate(@Param("from") LocalDate from, @Param("to") LocalDate to); +} diff --git a/src/main/java/com/swyp/picke/domain/attendance/repository/AttendanceStreakRepository.java b/src/main/java/com/swyp/picke/domain/attendance/repository/AttendanceStreakRepository.java new file mode 100644 index 00000000..57bc7615 --- /dev/null +++ b/src/main/java/com/swyp/picke/domain/attendance/repository/AttendanceStreakRepository.java @@ -0,0 +1,11 @@ +package com.swyp.picke.domain.attendance.repository; + +import com.swyp.picke.domain.attendance.entity.AttendanceStreak; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.Optional; + +public interface AttendanceStreakRepository extends JpaRepository { + + Optional findByUserId(Long userId); +} diff --git a/src/main/java/com/swyp/picke/domain/attendance/scheduler/AttendanceWeeklyResetScheduler.java b/src/main/java/com/swyp/picke/domain/attendance/scheduler/AttendanceWeeklyResetScheduler.java new file mode 100644 index 00000000..7f31e6d1 --- /dev/null +++ b/src/main/java/com/swyp/picke/domain/attendance/scheduler/AttendanceWeeklyResetScheduler.java @@ -0,0 +1,46 @@ +package com.swyp.picke.domain.attendance.scheduler; + +import com.swyp.picke.domain.attendance.entity.AttendanceStreak; +import com.swyp.picke.domain.attendance.repository.AttendanceStreakRepository; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + +import java.time.DayOfWeek; +import java.time.LocalDate; +import java.time.ZoneId; +import java.time.temporal.TemporalAdjusters; +import java.util.List; + +/** + * 매주 월요일 00:00 (KST) 에 연속 출석 카운트를 초기화한다. + * + * - current_streak, is_streak_achieved 를 0 / false 로 초기화 + * - streak_week_start 를 이번 주 월요일로 업데이트 + * - max_streak 는 유지 (최장 기록 보존) + */ +@Slf4j +@Component +@RequiredArgsConstructor +public class AttendanceWeeklyResetScheduler { + + private static final ZoneId SEOUL_ZONE = ZoneId.of("Asia/Seoul"); + + private final AttendanceStreakRepository attendanceStreakRepository; + + @Scheduled(cron = "0 0 0 ? * MON", zone = "Asia/Seoul") + @Transactional + public void resetWeeklyStreak() { + LocalDate thisMonday = LocalDate.now(SEOUL_ZONE) + .with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY)); + + log.info("[AttendanceWeeklyReset] start weekStart={}", thisMonday); + + List streaks = attendanceStreakRepository.findAll(); + streaks.forEach(streak -> streak.initWeek(thisMonday)); + + log.info("[AttendanceWeeklyReset] end count={}", streaks.size()); + } +} diff --git a/src/main/java/com/swyp/picke/domain/attendance/service/AttendanceService.java b/src/main/java/com/swyp/picke/domain/attendance/service/AttendanceService.java new file mode 100644 index 00000000..32f46a55 --- /dev/null +++ b/src/main/java/com/swyp/picke/domain/attendance/service/AttendanceService.java @@ -0,0 +1,204 @@ +package com.swyp.picke.domain.attendance.service; + +import com.swyp.picke.domain.attendance.dto.response.AttendanceResponse.CheckResponse; +import com.swyp.picke.domain.attendance.dto.response.AttendanceResponse.SummaryResponse; +import com.swyp.picke.domain.attendance.dto.response.AttendanceResponse.WeeklyResponse; +import com.swyp.picke.domain.attendance.dto.response.AttendanceResponse.WeeklyResponse.DayAttendance; +import com.swyp.picke.domain.attendance.entity.AttendanceRecord; +import com.swyp.picke.domain.attendance.entity.AttendanceStreak; +import com.swyp.picke.domain.attendance.enums.AttendanceStatus; +import com.swyp.picke.domain.attendance.repository.AttendanceRecordRepository; +import com.swyp.picke.domain.attendance.repository.AttendanceStreakRepository; +import com.swyp.picke.domain.user.entity.User; +import com.swyp.picke.domain.user.enums.CreditType; +import com.swyp.picke.domain.user.repository.UserRepository; +import com.swyp.picke.domain.user.service.CreditService; +import com.swyp.picke.domain.user.service.UserService; +import com.swyp.picke.global.common.exception.CustomException; +import com.swyp.picke.global.common.exception.ErrorCode; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.time.DayOfWeek; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.time.temporal.TemporalAdjusters; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +@Service +@RequiredArgsConstructor +@Transactional(readOnly = true) +public class AttendanceService { + + private static final ZoneId SEOUL_ZONE = ZoneId.of("Asia/Seoul"); + private static final int STREAK_BONUS_THRESHOLD = 7; + private static final int STREAK_REWARD_POINTS = CreditType.ATTENDANCE_STREAK.getDefaultAmount(); + + private final AttendanceRecordRepository attendanceRecordRepository; + private final AttendanceStreakRepository attendanceStreakRepository; + private final UserService userService; + private final UserRepository userRepository; + private final CreditService creditService; + + @Transactional + public CheckResponse check() { + User user = userService.findCurrentUser(); + LocalDate today = LocalDate.now(SEOUL_ZONE); + + if (attendanceRecordRepository.existsByUserIdAndAttendedDate(user.getId(), today)) { + throw new CustomException(ErrorCode.ATTENDANCE_ALREADY_CHECKED); + } + + int dailyPoints = CreditType.TODAY_CREDIT.getDefaultAmount(); + AttendanceRecord record = AttendanceRecord.builder() + .user(user) + .attendedDate(today) + .pointsEarned(dailyPoints) + .build(); + attendanceRecordRepository.save(record); + + Long referenceId = toDateLong(today); + creditService.addCredit(user.getId(), CreditType.TODAY_CREDIT, referenceId); + + AttendanceStreak streak = getOrCreateStreak(user, today); + boolean streakBonusEarned = updateStreak(streak, today, user.getId()); + + int streakBonusPoints = streakBonusEarned ? STREAK_REWARD_POINTS : 0; + int totalPoints = creditService.getTotalPoints(user.getId()); + + return new CheckResponse( + user.getUserTag(), + LocalDateTime.now(SEOUL_ZONE), + dailyPoints, + streakBonusEarned, + streakBonusPoints, + streak.getCurrentStreak(), + totalPoints + ); + } + + public WeeklyResponse getWeekly() { + User user = userService.findCurrentUser(); + LocalDate today = LocalDate.now(SEOUL_ZONE); + LocalDate monday = today.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY)); + LocalDate sunday = monday.plusDays(6); + + List records = + attendanceRecordRepository.findByUserIdAndAttendedDateBetween(user.getId(), monday, sunday); + + Set attendedDates = records.stream() + .map(AttendanceRecord::getAttendedDate) + .collect(Collectors.toSet()); + + String[] dayLabels = {"MON", "TUE", "WED", "THU", "FRI", "SAT", "SUN"}; + List weeklyAttendance = new ArrayList<>(); + + for (int i = 0; i < 7; i++) { + LocalDate date = monday.plusDays(i); + AttendanceStatus status; + int points = 0; + + if (attendedDates.contains(date)) { + status = AttendanceStatus.ATTENDED; + points = CreditType.TODAY_CREDIT.getDefaultAmount(); + } else if (date.equals(today)) { + status = AttendanceStatus.PENDING; + } else { + status = AttendanceStatus.NOT_ATTENDED; + } + + weeklyAttendance.add(new DayAttendance(dayLabels[i], date, status, points)); + } + + AttendanceStreak streak = attendanceStreakRepository.findByUserId(user.getId()).orElse(null); + int currentStreak = streak != null ? streak.getCurrentStreak() : 0; + boolean isStreakAchieved = streak != null && streak.isStreakAchieved(); + + return new WeeklyResponse( + user.getUserTag(), + monday, + currentStreak, + isStreakAchieved, + weeklyAttendance, + STREAK_REWARD_POINTS + ); + } + + public SummaryResponse getSummary() { + User user = userService.findCurrentUser(); + + long totalAttendedDays = attendanceRecordRepository.countByUserId(user.getId()); + + AttendanceStreak streak = attendanceStreakRepository.findByUserId(user.getId()).orElse(null); + int currentStreak = streak != null ? streak.getCurrentStreak() : 0; + int maxStreak = streak != null ? streak.getMaxStreak() : 0; + + int totalPoints = creditService.getTotalPoints(user.getId()); + + LocalDateTime lastAttendedAt = attendanceRecordRepository + .findTopByUserIdOrderByAttendedDateDesc(user.getId()) + .map(r -> r.getAttendedDate().atStartOfDay()) + .orElse(null); + + return new SummaryResponse( + user.getUserTag(), + totalAttendedDays, + currentStreak, + maxStreak, + totalPoints, + lastAttendedAt + ); + } + + private AttendanceStreak getOrCreateStreak(User user, LocalDate today) { + LocalDate weekStart = today.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY)); + return attendanceStreakRepository.findByUserId(user.getId()) + .orElseGet(() -> { + // detached User 대신 같은 영속성 컨텍스트에서 다시 조회 + User managedUser = userRepository.findById(user.getId()) + .orElseThrow(() -> new CustomException(ErrorCode.USER_NOT_FOUND)); + return attendanceStreakRepository.save( + AttendanceStreak.builder() + .user(managedUser) + .currentStreak(0) + .maxStreak(0) + .streakWeekStart(weekStart) + .isStreakAchieved(false) + .build() + ); + }); + } + + private boolean updateStreak(AttendanceStreak streak, LocalDate today, Long userId) { + LocalDate yesterday = today.minusDays(1); + boolean continuedStreak = attendanceRecordRepository + .existsByUserIdAndAttendedDate(userId, yesterday); + + if (continuedStreak || streak.getCurrentStreak() == 0) { + streak.attend(today); + } else { + LocalDate weekStart = today.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY)); + streak.resetStreak(weekStart); + } + + boolean justAchieved = streak.getCurrentStreak() >= STREAK_BONUS_THRESHOLD + && streak.isStreakAchieved() + && !creditService.existsHistory(userId, CreditType.ATTENDANCE_STREAK, toDateLong(streak.getStreakWeekStart()) + 7L); + + if (justAchieved) { + Long streakReferenceId = toDateLong(streak.getStreakWeekStart()) + 7L; + creditService.addCredit(userId, CreditType.ATTENDANCE_STREAK, streakReferenceId); + } + + return justAchieved; + } + + private Long toDateLong(LocalDate date) { + return Long.parseLong(date.toString().replace("-", "")); + } +} diff --git a/src/main/java/com/swyp/picke/domain/user/enums/CreditType.java b/src/main/java/com/swyp/picke/domain/user/enums/CreditType.java index 845a633a..03519c34 100644 --- a/src/main/java/com/swyp/picke/domain/user/enums/CreditType.java +++ b/src/main/java/com/swyp/picke/domain/user/enums/CreditType.java @@ -5,6 +5,7 @@ @Getter public enum CreditType { TODAY_CREDIT(5), // 출석체크: 하루 1회 + ATTENDANCE_STREAK(7), // 7일 연속 출석 보너스 DEFAULT_CREDIT(30), // 기본 크레딧: 회원가입 시 기본 지급 BATTLE_VOTE(5), // 배틀 참여 보상: 사후 투표 완료 시 즉시 지급 BATTLE_ENTRY(-5), // 지난 배틀 이용 비용: 사전 투표 최초 진입 시 차감 diff --git a/src/main/java/com/swyp/picke/domain/user/service/CreditService.java b/src/main/java/com/swyp/picke/domain/user/service/CreditService.java index 2a024dac..bab5b81c 100644 --- a/src/main/java/com/swyp/picke/domain/user/service/CreditService.java +++ b/src/main/java/com/swyp/picke/domain/user/service/CreditService.java @@ -116,4 +116,11 @@ private void validateReferenceId(Long referenceId) { throw new CustomException(ErrorCode.CREDIT_REFERENCE_REQUIRED); } } + + /** + * 크레딧 적립/소비 기록 조회 + */ + public boolean existsHistory(Long userId, CreditType creditType, Long referenceId) { + return creditHistoryRepository.existsByUserIdAndCreditTypeAndReferenceId(userId, creditType, referenceId); + } } diff --git a/src/main/java/com/swyp/picke/global/common/exception/ErrorCode.java b/src/main/java/com/swyp/picke/global/common/exception/ErrorCode.java index ce7d66f7..046d7070 100644 --- a/src/main/java/com/swyp/picke/global/common/exception/ErrorCode.java +++ b/src/main/java/com/swyp/picke/global/common/exception/ErrorCode.java @@ -111,7 +111,10 @@ public enum ErrorCode { // MyPage PHILOSOPHER_CALC_FAILED(HttpStatus.INTERNAL_SERVER_ERROR, "USER_500_PHIL", "철학자 유형을 계산할 수 없습니다."), - RECAP_NOT_FOUND(HttpStatus.NOT_FOUND, "USER_404_RECAP", "존재하지 않는 리캡입니다."); + RECAP_NOT_FOUND(HttpStatus.NOT_FOUND, "USER_404_RECAP", "존재하지 않는 리캡입니다."), + + // Attendance + ATTENDANCE_ALREADY_CHECKED(HttpStatus.CONFLICT, "ATTENDANCE_409", "오늘 이미 출석체크를 완료했습니다."); private final HttpStatus httpStatus; private final String code; diff --git a/src/main/java/com/swyp/picke/global/config/SwaggerConfig.java b/src/main/java/com/swyp/picke/global/config/SwaggerConfig.java index d2af2a51..625fa29b 100644 --- a/src/main/java/com/swyp/picke/global/config/SwaggerConfig.java +++ b/src/main/java/com/swyp/picke/global/config/SwaggerConfig.java @@ -72,7 +72,11 @@ public class SwaggerConfig { "GET /api/v1/share/recap/{shareKey}", "POST /api/v1/battles/proposals", "GET /api/v1/battles/{battleId}/recommendations/interesting", - "GET /api/v1/battles/{battleId}/scenario" + "GET /api/v1/battles/{battleId}/scenario", + // Attendance + "POST /api/v1/attendance/check", + "GET /api/v1/attendance/weekly", + "GET /api/v1/attendance/summary" ); @Bean From 77db7a150e492948450a987984b4a0e5b296bd1e Mon Sep 17 00:00:00 2001 From: Youwol <153346797+si-zero@users.noreply.github.com> Date: Thu, 4 Jun 2026 18:00:41 +0900 Subject: [PATCH 05/29] =?UTF-8?q?#260=20[Feat]=20=EC=8A=A4=EC=9B=A8?= =?UTF-8?q?=EA=B1=B0=20=EC=96=B4=EB=93=9C=EB=AF=BC/=EC=9C=A0=EC=A0=80=20?= =?UTF-8?q?=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/AdminAttendanceController.java | 2 -- .../controller/AdminBattleController.java | 2 -- .../AdminNotificationController.java | 2 -- .../controller/AdminPickeController.java | 2 +- .../admin/controller/AdminPollController.java | 2 -- .../admin/controller/AdminQuizController.java | 2 -- .../controller/AdminScenarioController.java | 2 -- .../admin/controller/AdminTagController.java | 2 -- .../AdminBattleProposalController.java | 2 -- .../BestCommentSchedulerTestController.java | 2 -- .../controller/AdMobRewardController.java | 2 -- .../vote/controller/VoteController.java | 3 -- .../picke/global/config/SwaggerConfig.java | 28 ++++++++++++++++++- .../s3/controller/FileUploadController.java | 2 -- .../ResourceRedirectController.java | 2 -- 15 files changed, 28 insertions(+), 29 deletions(-) diff --git a/src/main/java/com/swyp/picke/domain/admin/controller/AdminAttendanceController.java b/src/main/java/com/swyp/picke/domain/admin/controller/AdminAttendanceController.java index e00ef3b6..2e9ee19c 100644 --- a/src/main/java/com/swyp/picke/domain/admin/controller/AdminAttendanceController.java +++ b/src/main/java/com/swyp/picke/domain/admin/controller/AdminAttendanceController.java @@ -4,7 +4,6 @@ import com.swyp.picke.domain.admin.dto.attendance.response.AdminAttendanceResponse.UserAttendanceResponse; import com.swyp.picke.domain.admin.service.AdminAttendanceService; import com.swyp.picke.global.common.response.ApiResponse; -import io.swagger.v3.oas.annotations.Hidden; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; @@ -18,7 +17,6 @@ import java.time.LocalDate; -@Hidden @Tag(name = "관리자 출석체크 API", description = "출석 현황 집계 및 특정 유저 출석 이력 조회") @RestController @RequestMapping("/api/v1/admin/attendance") diff --git a/src/main/java/com/swyp/picke/domain/admin/controller/AdminBattleController.java b/src/main/java/com/swyp/picke/domain/admin/controller/AdminBattleController.java index 9fbb1399..327f4815 100644 --- a/src/main/java/com/swyp/picke/domain/admin/controller/AdminBattleController.java +++ b/src/main/java/com/swyp/picke/domain/admin/controller/AdminBattleController.java @@ -6,7 +6,6 @@ import com.swyp.picke.domain.admin.dto.battle.request.AdminBattleUpdateRequest; import com.swyp.picke.domain.admin.service.AdminBattleService; import com.swyp.picke.global.common.response.ApiResponse; -import io.swagger.v3.oas.annotations.Hidden; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.validation.Valid; @@ -23,7 +22,6 @@ import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; -@Hidden @Tag(name = "관리자 배틀 API", description = "관리자 배틀 콘텐츠 생성, 조회, 수정, 삭제") @RestController @RequestMapping("/api/v1/admin/battles") diff --git a/src/main/java/com/swyp/picke/domain/admin/controller/AdminNotificationController.java b/src/main/java/com/swyp/picke/domain/admin/controller/AdminNotificationController.java index c9427d1c..bfb1cd16 100644 --- a/src/main/java/com/swyp/picke/domain/admin/controller/AdminNotificationController.java +++ b/src/main/java/com/swyp/picke/domain/admin/controller/AdminNotificationController.java @@ -6,7 +6,6 @@ import com.swyp.picke.domain.admin.service.AdminNotificationService; import com.swyp.picke.domain.notification.enums.NotificationCategory; import com.swyp.picke.global.common.response.ApiResponse; -import io.swagger.v3.oas.annotations.Hidden; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.validation.Valid; @@ -20,7 +19,6 @@ import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; -@Hidden @Tag(name = "관리자 공지 API", description = "공지사항/이벤트 작성 및 조회") @RestController @RequestMapping("/api/v1/admin/notices") diff --git a/src/main/java/com/swyp/picke/domain/admin/controller/AdminPickeController.java b/src/main/java/com/swyp/picke/domain/admin/controller/AdminPickeController.java index 45a5031a..e190d6a7 100644 --- a/src/main/java/com/swyp/picke/domain/admin/controller/AdminPickeController.java +++ b/src/main/java/com/swyp/picke/domain/admin/controller/AdminPickeController.java @@ -7,7 +7,7 @@ import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; -@Hidden // 스웨거 노출 차단 +@Hidden @Controller @RequestMapping("/api/v1/admin") public class AdminPickeController { diff --git a/src/main/java/com/swyp/picke/domain/admin/controller/AdminPollController.java b/src/main/java/com/swyp/picke/domain/admin/controller/AdminPollController.java index 5bb2d031..80898ec1 100644 --- a/src/main/java/com/swyp/picke/domain/admin/controller/AdminPollController.java +++ b/src/main/java/com/swyp/picke/domain/admin/controller/AdminPollController.java @@ -6,7 +6,6 @@ import com.swyp.picke.domain.admin.dto.poll.response.AdminPollDetailResponse; import com.swyp.picke.domain.admin.service.AdminPollService; import com.swyp.picke.global.common.response.ApiResponse; -import io.swagger.v3.oas.annotations.Hidden; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.validation.Valid; @@ -22,7 +21,6 @@ import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; -@Hidden @Tag(name = "관리자 투표 콘텐츠 API", description = "관리자 투표 콘텐츠 생성, 조회, 수정, 삭제") @RestController @RequestMapping("/api/v1/admin/polls") diff --git a/src/main/java/com/swyp/picke/domain/admin/controller/AdminQuizController.java b/src/main/java/com/swyp/picke/domain/admin/controller/AdminQuizController.java index 4ded5c7d..5eaacd53 100644 --- a/src/main/java/com/swyp/picke/domain/admin/controller/AdminQuizController.java +++ b/src/main/java/com/swyp/picke/domain/admin/controller/AdminQuizController.java @@ -6,7 +6,6 @@ import com.swyp.picke.domain.admin.dto.quiz.response.AdminQuizDetailResponse; import com.swyp.picke.domain.admin.service.AdminQuizService; import com.swyp.picke.global.common.response.ApiResponse; -import io.swagger.v3.oas.annotations.Hidden; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.validation.Valid; @@ -22,7 +21,6 @@ import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; -@Hidden @Tag(name = "관리자 퀴즈 API", description = "관리자 퀴즈 콘텐츠 생성, 조회, 수정, 삭제") @RestController @RequestMapping("/api/v1/admin/quizzes") diff --git a/src/main/java/com/swyp/picke/domain/admin/controller/AdminScenarioController.java b/src/main/java/com/swyp/picke/domain/admin/controller/AdminScenarioController.java index 09d7d030..97de81d6 100644 --- a/src/main/java/com/swyp/picke/domain/admin/controller/AdminScenarioController.java +++ b/src/main/java/com/swyp/picke/domain/admin/controller/AdminScenarioController.java @@ -8,7 +8,6 @@ import com.swyp.picke.domain.admin.dto.scenario.response.AdminScenarioResponse; import com.swyp.picke.domain.admin.service.AdminScenarioService; import com.swyp.picke.global.common.response.ApiResponse; -import io.swagger.v3.oas.annotations.Hidden; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; @@ -25,7 +24,6 @@ import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestController; -@Hidden @Tag(name = "관리자 시나리오 API", description = "관리자 시나리오 생성, 조회, 수정, 삭제") @RestController @RequestMapping("/api/v1/admin") diff --git a/src/main/java/com/swyp/picke/domain/admin/controller/AdminTagController.java b/src/main/java/com/swyp/picke/domain/admin/controller/AdminTagController.java index bd4d48cc..b8fff02a 100644 --- a/src/main/java/com/swyp/picke/domain/admin/controller/AdminTagController.java +++ b/src/main/java/com/swyp/picke/domain/admin/controller/AdminTagController.java @@ -5,7 +5,6 @@ import com.swyp.picke.domain.admin.dto.tag.response.TagResponse; import com.swyp.picke.domain.admin.service.AdminTagService; import com.swyp.picke.global.common.response.ApiResponse; -import io.swagger.v3.oas.annotations.Hidden; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; @@ -20,7 +19,6 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; -@Hidden @Tag(name = "관리자 태그 API", description = "관리자 태그 생성, 수정, 삭제") @RestController @RequiredArgsConstructor diff --git a/src/main/java/com/swyp/picke/domain/battle/controller/AdminBattleProposalController.java b/src/main/java/com/swyp/picke/domain/battle/controller/AdminBattleProposalController.java index 1962ea7e..04f7fa21 100644 --- a/src/main/java/com/swyp/picke/domain/battle/controller/AdminBattleProposalController.java +++ b/src/main/java/com/swyp/picke/domain/battle/controller/AdminBattleProposalController.java @@ -4,7 +4,6 @@ import com.swyp.picke.domain.battle.dto.request.BattleProposalReviewRequest; import com.swyp.picke.domain.battle.service.BattleProposalService; import com.swyp.picke.global.common.response.ApiResponse; -import io.swagger.v3.oas.annotations.Hidden; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.validation.Valid; @@ -12,7 +11,6 @@ import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.*; -@Hidden @Tag(name = "관리자 배틀 제안 API", description = "주제 제안 목록 조회 및 채택/미채택 처리") @RestController @RequestMapping("/api/v1/admin/battles") diff --git a/src/main/java/com/swyp/picke/domain/perspective/controller/BestCommentSchedulerTestController.java b/src/main/java/com/swyp/picke/domain/perspective/controller/BestCommentSchedulerTestController.java index a9ac1478..552c30c5 100644 --- a/src/main/java/com/swyp/picke/domain/perspective/controller/BestCommentSchedulerTestController.java +++ b/src/main/java/com/swyp/picke/domain/perspective/controller/BestCommentSchedulerTestController.java @@ -2,7 +2,6 @@ import com.swyp.picke.domain.perspective.scheduler.BestCommentScheduler; import com.swyp.picke.global.common.response.ApiResponse; -import io.swagger.v3.oas.annotations.Hidden; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; @@ -11,7 +10,6 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; -@Hidden @Tag(name = "[Test] BestCommentScheduler", description = "스케줄러 테스트 API") @RestController @RequestMapping("/api/test/scheduler") diff --git a/src/main/java/com/swyp/picke/domain/reward/controller/AdMobRewardController.java b/src/main/java/com/swyp/picke/domain/reward/controller/AdMobRewardController.java index cbc0d6bf..88bb50e0 100644 --- a/src/main/java/com/swyp/picke/domain/reward/controller/AdMobRewardController.java +++ b/src/main/java/com/swyp/picke/domain/reward/controller/AdMobRewardController.java @@ -4,7 +4,6 @@ import com.swyp.picke.domain.reward.dto.response.AdMobRewardResponse; import com.swyp.picke.domain.reward.service.AdMobRewardService; import com.swyp.picke.global.common.response.ApiResponse; -import io.swagger.v3.oas.annotations.Hidden; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; @@ -14,7 +13,6 @@ import org.springframework.web.bind.annotation.RestController; @Slf4j -@Hidden @Tag(name = "보상 API", description = "AdMob 광고 보상 관련 API") @RestController @RequestMapping("/api/v1/admob") diff --git a/src/main/java/com/swyp/picke/domain/vote/controller/VoteController.java b/src/main/java/com/swyp/picke/domain/vote/controller/VoteController.java index e0c7835c..9e831a3f 100644 --- a/src/main/java/com/swyp/picke/domain/vote/controller/VoteController.java +++ b/src/main/java/com/swyp/picke/domain/vote/controller/VoteController.java @@ -145,7 +145,6 @@ public ApiResponse completeTts( return ApiResponse.onSuccess(null); } - @Hidden @Operation(summary = "[관리자] 배틀 투표 기록 삭제") @DeleteMapping("/admin/votes/battle/{battleId}") @PreAuthorize("hasRole('ADMIN')") @@ -154,7 +153,6 @@ public ApiResponse deleteBattleVote(@PathVariable Long battleId) { return ApiResponse.onSuccess(null); } - @Hidden @Operation(summary = "[관리자] 퀴즈 투표 기록 삭제") @DeleteMapping("/admin/votes/quiz/{battleId}") @PreAuthorize("hasRole('ADMIN')") @@ -163,7 +161,6 @@ public ApiResponse deleteQuizVote(@PathVariable Long battleId) { return ApiResponse.onSuccess(null); } - @Hidden @Operation(summary = "[관리자] 투표 콘텐츠 투표 기록 삭제") @DeleteMapping("/admin/votes/poll/{battleId}") @PreAuthorize("hasRole('ADMIN')") diff --git a/src/main/java/com/swyp/picke/global/config/SwaggerConfig.java b/src/main/java/com/swyp/picke/global/config/SwaggerConfig.java index 625fa29b..2aada9a9 100644 --- a/src/main/java/com/swyp/picke/global/config/SwaggerConfig.java +++ b/src/main/java/com/swyp/picke/global/config/SwaggerConfig.java @@ -12,6 +12,7 @@ import java.util.List; import java.util.Set; import org.springdoc.core.customizers.OpenApiCustomizer; +import org.springdoc.core.models.GroupedOpenApi; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -79,6 +80,32 @@ public class SwaggerConfig { "GET /api/v1/attendance/summary" ); + @Bean + public GroupedOpenApi userApi() { + return GroupedOpenApi.builder() + .group("1. 사용자 API") + .pathsToMatch("/api/v1/**") + .pathsToExclude("/api/v1/admin/**", "/api/v1/files/**", "/api/v1/resources/**", "/api/test/**", "/api/v1/admob/**") + .addOpenApiCustomizer(feUsedApiOnlyCustomizer()) + .build(); + } + + @Bean + public GroupedOpenApi adminApi() { + return GroupedOpenApi.builder() + .group("2. 관리자 API") + .pathsToMatch("/api/v1/admin/**", "/api/v1/files/**", "/api/v1/resources/**", "/api/test/**", "/api/v1/admob/**") + .build(); + } + + @Bean + public GroupedOpenApi allApi() { + return GroupedOpenApi.builder() + .group("0. 모든 API") + .pathsToMatch("/api/**") + .build(); + } + @Bean public OpenAPI openAPI() { // 1. 운영 서버 (8080) @@ -118,7 +145,6 @@ public OpenAPI openAPI() { .addSecurityItem(securityRequirement); } - @Bean public OpenApiCustomizer feUsedApiOnlyCustomizer() { return openApi -> { if (openApi.getPaths() == null) { diff --git a/src/main/java/com/swyp/picke/global/infra/s3/controller/FileUploadController.java b/src/main/java/com/swyp/picke/global/infra/s3/controller/FileUploadController.java index cb1bb13e..f96b656b 100644 --- a/src/main/java/com/swyp/picke/global/infra/s3/controller/FileUploadController.java +++ b/src/main/java/com/swyp/picke/global/infra/s3/controller/FileUploadController.java @@ -6,7 +6,6 @@ import com.swyp.picke.global.infra.s3.enums.FileCategory; import com.swyp.picke.global.infra.s3.service.S3PresignedUrlService; import com.swyp.picke.global.infra.s3.service.S3UploadService; -import io.swagger.v3.oas.annotations.Hidden; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.media.Content; @@ -25,7 +24,6 @@ import java.io.IOException; import java.util.UUID; -@Hidden @Tag(name = "파일 업로드 API", description = "관리자 파일 업로드 (S3 / 로컬 임시저장)") @RestController @RequestMapping("/api/v1/files") diff --git a/src/main/java/com/swyp/picke/global/infra/s3/controller/ResourceRedirectController.java b/src/main/java/com/swyp/picke/global/infra/s3/controller/ResourceRedirectController.java index 3fd2b256..ca49e862 100644 --- a/src/main/java/com/swyp/picke/global/infra/s3/controller/ResourceRedirectController.java +++ b/src/main/java/com/swyp/picke/global/infra/s3/controller/ResourceRedirectController.java @@ -3,7 +3,6 @@ import com.swyp.picke.global.infra.local.service.LocalDraftFileStorageService; import com.swyp.picke.global.infra.s3.enums.FileCategory; import com.swyp.picke.global.infra.s3.service.S3PresignedUrlService; -import io.swagger.v3.oas.annotations.Hidden; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; @@ -18,7 +17,6 @@ import java.net.URI; -@Hidden @Tag(name = "리소스 리다이렉트 API", description = "공개 리소스 요청을 S3 Presigned URL 또는 로컬 임시파일로 전달") @RestController @RequestMapping("/api/v1/resources") From a9d4293917e924743d6896042400ca4ca7c95b78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A4=80=ED=98=81?= <127603139+HYH0804@users.noreply.github.com> Date: Thu, 11 Jun 2026 23:38:59 +0900 Subject: [PATCH 06/29] =?UTF-8?q?[Feat]=20=EC=95=8C=EB=A6=BC=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20(#263)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## #️⃣연관된 이슈 - #262 ## 📝 작업 내용 ### ✨ Feat | 내용 | 파일 | |------|------| | 디바이스 푸시 토큰 등록/해제 API 추가 (Android: FCM 토큰, iOS: APNs 디바이스 토큰) | `DeviceController.java`, `DeviceService.java`, `RegisterDeviceRequest.java`, `UserDevice.java`, `DevicePlatform.java`, `UserDeviceRepository.java` | | FCM(Android) 푸시 발송 인프라 구축 (Firebase Admin SDK) | `FirebaseConfig.java`, `FcmPushService.java`, `build.gradle` | | iOS 푸시를 FCM 경유 방식에서 다이렉트 APNs 발송으로 전환 (Pushy) | `ApnsConfig.java`, `ApnsPushService.java`, `FcmPushService.java`, `NotificationDispatchService.java`, `build.gradle` | | 새 배틀 발행 시 인앱 알림 + 푸시 발송 | `BattleServiceImpl.java`, `NotificationDispatchService.java` | | 답글 좋아요 / 새 댓글 발생 시 인앱 알림 + 푸시 발송 | `CommentLikeService.java`, `PerspectiveCommentService.java`, `NotificationDispatchService.java` | | 포인트 적립 시 인앱 알림 발송 | `CreditService.java` | | 알림 API 명세 문서 작성 | `docs/api-specs/notification-api.md` | ### ♻️ Refactor | 내용 | 파일 | |------|------| | 답글 좋아요/새 댓글 알림 문구에 배틀 제목 포함하도록 개선 | `NotificationDispatchService.java`, `CommentLikeService.java`, `PerspectiveCommentService.java` | ### 🐛 Fix | 내용 | 파일 | |------|------| | 컨테이너 배포 환경(Railway)에서 FCM/APNs 자격증명 파일(JSON/.p8)을 읽지 못해 서버 기동 자체가 실패하던 문제 수정 — S3에서 자격증명을 다운로드해 사용하도록 변경 (로컬은 기존 파일 경로 방식 그대로 폴백) | `FirebaseConfig.java`, `ApnsConfig.java`, `application.yml` | ## 📌 공유 사항 > 1. **(중요) Railway dev Variables 추가 완료** — 이 PR이 배포되려면 아래 값이 필요하며, dev 환경엔 이미 세팅해뒀습니다. > - `FCM_CREDENTIALS_S3_KEY`, `APNS_CREDENTIALS_S3_KEY` (S3 `pique-bucket/credentials/`에 Firebase 서비스 계정 JSON, APNs `.p8` 키 업로드 완료) > - `APNS_ENABLED=true`, `APNS_KEY_ID`, `APNS_BUNDLE_ID`, `APNS_PRODUCTION` > - `APNS_TEAM_ID`는 따로 안 넣어도 기존 `APPLE_TEAM_ID`로 폴백됩니다. > 2. **운영(main) 배포 시에도 동일하게 Railway 변수 추가 + S3 파일 업로드가 필요**합니다. > 3. iOS는 더 이상 FCM을 거치지 않고 서버가 APNs로 직접 발송합니다. 디바이스 등록 시 `fcmToken` 필드에 iOS는 APNs 디바이스 토큰(hex 문자열)을 보내야 합니다. 자세한 내용은 `docs/api-specs/notification-api.md` 참고. > 4. 새 의존성 추가: `firebase-admin:9.9.0`, `com.eatthepath:pushy:0.15.4` ## ✅ 체크리스트 - [x] Reviewer에 팀원들을 선택했나요? - [x] Assignees에 본인을 선택했나요? - [x] 컨벤션에 맞는 Type을 선택했나요? - [x] Development에 이슈를 연동했나요? - [x] Merge 하려는 브랜치가 올바르게 설정되어 있나요? - [x] 컨벤션을 지키고 있나요? - [x] 로컬에서 실행했을 때 에러가 발생하지 않나요? - [x] 팀원들에게 PR 링크 공유를 했나요? ## 📸 스크린샷 ## 💬 리뷰 요구사항 > 1. APNs 환경(sandbox/production)이 `APNS_PRODUCTION` 전역 설정 1개로 고정되는 구조인데, 개발(TestFlight)/운영(App Store) 빌드를 동시에 지원하려면 별도 설계가 필요해 보입니다 — 의견 부탁드립니다. > 2. FCM/APNs 자격증명을 S3에서 받아오는 방식(이번 Fix)이 적절한지, 다른 방식을 선호하시면 의견 부탁드립니다. --------- Co-authored-by: 현준혁 Co-authored-by: Claude Sonnet 4.6 --- build.gradle | 6 + docs/api-specs/notification-api.md | 313 ++++++++++++++++++ .../battle/service/BattleServiceImpl.java | 19 ++ .../controller/DeviceController.java | 45 +++ .../dto/request/RegisterDeviceRequest.java | 17 + .../response/NotificationDetailResponse.java | 1 + .../response/NotificationSummaryResponse.java | 1 + .../notification/entity/Notification.java | 6 +- .../notification/entity/UserDevice.java | 54 +++ .../notification/enums/DevicePlatform.java | 6 + .../enums/NotificationDetailCode.java | 4 +- .../repository/UserDeviceRepository.java | 19 ++ .../notification/service/DeviceService.java | 44 +++ .../service/NotificationDispatchService.java | 95 ++++++ .../service/NotificationService.java | 8 + .../service/CommentLikeService.java | 25 ++ .../service/PerspectiveCommentService.java | 29 ++ .../domain/user/service/CreditService.java | 32 ++ .../swyp/picke/global/config/ApnsConfig.java | 77 +++++ .../picke/global/config/FirebaseConfig.java | 61 ++++ .../infra/apns/service/ApnsPushService.java | 75 +++++ .../infra/fcm/service/FcmPushService.java | 40 +++ src/main/resources/application.yml | 17 + 23 files changed, 992 insertions(+), 2 deletions(-) create mode 100644 docs/api-specs/notification-api.md create mode 100644 src/main/java/com/swyp/picke/domain/notification/controller/DeviceController.java create mode 100644 src/main/java/com/swyp/picke/domain/notification/dto/request/RegisterDeviceRequest.java create mode 100644 src/main/java/com/swyp/picke/domain/notification/entity/UserDevice.java create mode 100644 src/main/java/com/swyp/picke/domain/notification/enums/DevicePlatform.java create mode 100644 src/main/java/com/swyp/picke/domain/notification/repository/UserDeviceRepository.java create mode 100644 src/main/java/com/swyp/picke/domain/notification/service/DeviceService.java create mode 100644 src/main/java/com/swyp/picke/domain/notification/service/NotificationDispatchService.java create mode 100644 src/main/java/com/swyp/picke/global/config/ApnsConfig.java create mode 100644 src/main/java/com/swyp/picke/global/config/FirebaseConfig.java create mode 100644 src/main/java/com/swyp/picke/global/infra/apns/service/ApnsPushService.java create mode 100644 src/main/java/com/swyp/picke/global/infra/fcm/service/FcmPushService.java diff --git a/build.gradle b/build.gradle index ed7174e5..f15bd9c1 100644 --- a/build.gradle +++ b/build.gradle @@ -58,6 +58,12 @@ dependencies { // Google Cloud TTS implementation 'com.google.cloud:google-cloud-texttospeech:2.58.0' + // Firebase Admin SDK (FCM 푸시 알림 - Android) + implementation 'com.google.firebase:firebase-admin:9.9.0' + + // Pushy (다이렉트 APNs 푸시 알림 - iOS) + implementation 'com.eatthepath:pushy:0.15.4' + // AWS S3 implementation 'io.awspring.cloud:spring-cloud-aws-starter-s3:3.3.0' diff --git a/docs/api-specs/notification-api.md b/docs/api-specs/notification-api.md new file mode 100644 index 00000000..ae82f976 --- /dev/null +++ b/docs/api-specs/notification-api.md @@ -0,0 +1,313 @@ +# 알림 API 명세서 (인앱 알림 + 푸시) + +--- + +## 1. 설계 메모 + +- 알림은 **인앱 알림(알림함)** 과 **푸시**, 두 트랙으로 동작합니다. + - 인앱 알림: `GET /api/v1/notifications`로 조회하는 알림함 데이터 + - 푸시: 앱이 백그라운드/종료 상태일 때 기기로 직접 발송되는 푸시. Android는 FCM, iOS는 APNs로 직접 발송됩니다. +- **NEW_BATTLE / COMMENT_LIKE / NEW_COMMENT** 는 인앱 알림 + 푸시 둘 다 발송됩니다. +- **CREDIT_EARNED / POLICY_CHANGE / PROMOTION** 은 인앱 알림만 발송됩니다 (푸시 없음). +- **VOTE_RESULT** 는 현재 보류 상태로, 발생하지 않습니다. +- 인증이 필요한 모든 API는 `Authorization: Bearer {access_token}` 헤더를 요구합니다. +- ⚠️ 이 도메인의 응답/요청 필드는 다른 API 문서(`snake_case`)와 달리 **`camelCase`** 입니다. (예: `notificationId`, `referenceId`, `perspectiveId`, `isRead`, `fcmToken`) + +### 1.1 `NotificationCategory` + +| 값 | 설명 | +|---|---| +| `ALL` | 전체 (목록 조회 시 필터 없음과 동일) | +| `CONTENT` | 콘텐츠 알림 (배틀, 답글 좋아요/댓글, 포인트 적립) | +| `NOTICE` | 공지사항 | +| `EVENT` | 이벤트/프로모션 | + +### 1.2 `detailCode` 목록 + +| detailCode | category | 기본 title | 채널 | referenceId 의미 | perspectiveId | +|---|---|---|---|---|---| +| `NEW_BATTLE` | CONTENT | 새로운 배틀이 시작되었어요 | 인앱 + 푸시 | battleId | - | +| `COMMENT_LIKE` | CONTENT | 내 답글에 좋아요가 달렸어요 | 인앱 + 푸시 | commentId | perspectiveId | +| `NEW_COMMENT` | CONTENT | 내 답글에 댓글이 달렸어요 | 인앱 + 푸시 | commentId | perspectiveId | +| `CREDIT_EARNED` | CONTENT | 포인트 적립 | 인앱만 | 적립 종류별로 다름(아래 참고) | - | +| `POLICY_CHANGE` | NOTICE | 공지사항 | 인앱만 | 없음(`null`) | - | +| `PROMOTION` | EVENT | 이벤트 | 인앱만 | 없음(`null`) | - | +| `VOTE_RESULT` | CONTENT | 투표 결과가 나왔어요 | (보류, 미발생) | - | - | + +`CREDIT_EARNED`의 `referenceId`는 적립 트리거에 따라 배틀 ID, 투표 ID, 제안 ID 등으로 다양하게 들어갈 수 있어 클라이언트에서 별도 화면 이동에 사용하지 않는 것을 권장합니다. `title`/`body` 텍스트만 표시하면 됩니다. + +--- + +## 2. 디바이스(푸시 토큰) 등록/해제 API + +### 2.1 `POST /api/v1/devices` + +로그인 성공 직후, 또는 푸시 토큰이 갱신될 때 호출합니다. 이미 등록된 토큰이면 현재 로그인한 유저로 재할당됩니다(같은 기기에서 계정을 바꿔 로그인하는 경우 대응). + +요청 헤더: + +- `Authorization: Bearer {access_token}` + +요청 바디: + +```json +{ + "fcmToken": "device_push_token_string", + "platform": "ANDROID" +} +``` + +| 필드 | 타입 | 필수 | 설명 | +|---|---|---|---| +| `fcmToken` | `string` | Y | `platform=ANDROID`이면 FCM 토큰, `platform=IOS`이면 APNs 디바이스 토큰(`didRegisterForRemoteNotificationsWithDeviceToken`에서 받은 토큰을 hex 문자열로 변환한 값) | +| `platform` | `string` | Y | `ANDROID` \| `IOS` | + +성공 응답 `200 OK`: + +```json +{ + "statusCode": 200, + "data": null, + "error": null +} +``` + +--- + +### 2.2 `DELETE /api/v1/devices` + +로그아웃 시 호출합니다. 등록되어 있지 않은 토큰을 보내도 에러 없이 `200`을 반환합니다(idempotent). + +요청 헤더: + +- `Authorization: Bearer {access_token}` + +쿼리 파라미터: + +| 파라미터 | 타입 | 필수 | 설명 | +|---|---|---|---| +| `fcmToken` | `string` | Y | 해제할 디바이스 푸시 토큰 | + +성공 응답 `200 OK`: + +```json +{ + "statusCode": 200, + "data": null, + "error": null +} +``` + +--- + +## 3. 알림함 API + +### 3.1 `GET /api/v1/notifications` + +알림함 목록을 최신순으로 조회합니다. + +요청 헤더: + +- `Authorization: Bearer {access_token}` + +쿼리 파라미터: + +| 파라미터 | 타입 | 필수 | 설명 | +|---|---|---|---| +| `category` | `string` | N | `ALL` \| `CONTENT` \| `NOTICE` \| `EVENT` (생략 시 전체) | +| `page` | `integer` | N | 페이지 번호 (기본값 `0`) | +| `size` | `integer` | N | 페이지 크기 (기본값 `20`) | + +성공 응답 `200 OK`: + +```json +{ + "statusCode": 200, + "data": { + "items": [ + { + "notificationId": 101, + "category": "CONTENT", + "detailCode": "NEW_BATTLE", + "title": "새로운 배틀이 시작되었어요", + "body": "\"민트초코, 호불호의 끝판왕\"에 지금 참여해보세요!", + "referenceId": 55, + "perspectiveId": null, + "isRead": false, + "createdAt": "2026-06-10T09:00:00" + }, + { + "notificationId": 100, + "category": "CONTENT", + "detailCode": "COMMENT_LIKE", + "title": "내 답글에 좋아요가 달렸어요", + "body": "\"민트초코, 호불호의 끝판왕\" 배틀에 남긴 내 답글에 좋아요가 달렸어요.", + "referenceId": 678, + "perspectiveId": 45, + "isRead": true, + "createdAt": "2026-06-09T18:30:00" + } + ], + "hasNext": false + }, + "error": null +} +``` + +탭(클릭) 시 화면 이동 로직은 [5. detailCode별 처리 가이드](#5-detailcode별-처리-가이드) 참고. + +--- + +### 3.2 `GET /api/v1/notifications/{notificationId}` + +알림 상세를 조회합니다. (목록과 동일한 필드 + `readAt`) + +요청 헤더: + +- `Authorization: Bearer {access_token}` + +성공 응답 `200 OK`: + +```json +{ + "statusCode": 200, + "data": { + "notificationId": 100, + "category": "CONTENT", + "detailCode": "COMMENT_LIKE", + "title": "내 답글에 좋아요가 달렸어요", + "body": "\"민트초코, 호불호의 끝판왕\" 배틀에 남긴 내 답글에 좋아요가 달렸어요.", + "referenceId": 678, + "perspectiveId": 45, + "isRead": true, + "createdAt": "2026-06-09T18:30:00", + "readAt": "2026-06-09T19:00:00" + }, + "error": null +} +``` + +예외 응답 `404 - 알림 없음`: + +```json +{ + "statusCode": 404, + "data": null, + "error": { + "code": "NOTIFICATION_404", + "message": "존재하지 않는 알림입니다." + } +} +``` + +--- + +### 3.3 `PATCH /api/v1/notifications/{notificationId}/read` + +알림 1건을 읽음 처리합니다. + +요청 헤더: + +- `Authorization: Bearer {access_token}` + +성공 응답 `200 OK`: + +```json +{ + "statusCode": 200, + "data": null, + "error": null +} +``` + +--- + +### 3.4 `PATCH /api/v1/notifications/read-all` + +알림함의 모든 알림을 읽음 처리합니다. + +요청 헤더: + +- `Authorization: Bearer {access_token}` + +성공 응답 `200 OK`: + +```json +{ + "statusCode": 200, + "data": null, + "error": null +} +``` + +--- + +## 4. 푸시 처리 가이드 (Android: FCM / iOS: APNs) + +`NEW_BATTLE`, `COMMENT_LIKE`, `NEW_COMMENT` 발생 시 등록된 디바이스로 푸시가 발송됩니다. Android는 FCM, iOS는 FCM을 거치지 않고 APNs로 직접 발송되며, 플랫폼별 메시지 구성이 다르므로 주의해주세요. + +### 4.1 Android (FCM) + +- **data-only** 메시지로 발송됩니다 (notification 블록 없음). +- 앱이 직접 `data`를 파싱해 로컬 알림(Notification)을 생성하고, 알림 탭 시에도 `data`로 라우팅을 처리해야 합니다. + +### 4.2 iOS (APNs 직접 발송) + +- FCM을 거치지 않고 서버가 APNs로 직접 발송하는 **alert(`aps.alert`) + 커스텀 데이터** 페이로드입니다. 커스텀 데이터(`type`, `battleId`, `url` 등)는 `aps`와 동일 레벨의 top-level 키로 들어갑니다. +- OS가 자동으로 알림을 표시합니다. 알림 탭 시 `userInfo`의 커스텀 키(또는 `url`의 유니버설 링크)로 라우팅합니다. +- `apple-app-site-association`이 `paths: ["*"]` 와일드카드로 설정되어 있어, `url`에 포함된 모든 경로가 유니버설 링크로 동작합니다. 별도 서버 설정 변경 없이 사용 가능합니다. +- **Firebase SDK가 더 이상 필요하지 않습니다.** 디바이스 등록 시 보내는 토큰은 FCM 토큰이 아니라 `didRegisterForRemoteNotificationsWithDeviceToken`에서 받는 APNs 디바이스 토큰(hex 문자열)입니다. +- 서버의 APNs 환경(sandbox/production)은 전역 설정 1개로 고정됩니다. 개발/TestFlight 빌드(sandbox 토큰)와 App Store 빌드(production 토큰)를 동시에 지원하려면 별도 협의가 필요합니다. + +### 4.3 `data` 페이로드 포맷 + +**NEW_BATTLE** + +```json +{ + "type": "BATTLE", + "battleId": "55", + "url": "https://picke.store/battle/55" +} +``` + +**COMMENT_LIKE / NEW_COMMENT** + +```json +{ + "type": "COMMENT", + "perspectiveId": "45", + "commentId": "678", + "url": "https://picke.store/perspective/45?commentId=678" +} +``` + +> `data`의 모든 값은 FCM 규격상 문자열(string)입니다. ID 값을 정수로 파싱해서 사용해주세요. + +탭 시 `type` 값으로 분기: + +- `"BATTLE"` → `battleId`로 배틀 상세 화면 이동 +- `"COMMENT"` → `perspectiveId`로 관점(댓글) 화면 이동 후 `commentId` 위치로 스크롤/하이라이트 + +푸시 데이터에는 알림함의 `notificationId`가 포함되어 있지 않습니다. 푸시 탭 후 별도로 읽음 처리가 필요하면 알림함 목록에서 동일 `referenceId`/`perspectiveId`를 가진 항목을 찾아 `PATCH /api/v1/notifications/{notificationId}/read`를 호출해주세요. + +--- + +## 5. detailCode별 처리 가이드 + +| detailCode | 탭(클릭) 시 동작 | +|---|---| +| `NEW_BATTLE` | `referenceId`(=battleId)로 배틀 상세 화면 이동 | +| `COMMENT_LIKE` / `NEW_COMMENT` | `perspectiveId`로 관점 화면 이동 후 `referenceId`(=commentId) 위치로 스크롤/하이라이트 | +| `CREDIT_EARNED` | 별도 이동 없음. `title` / `body` 텍스트만 표시 | +| `POLICY_CHANGE` / `PROMOTION` | 별도 이동 없음. `title` / `body` 텍스트만 표시 | + +--- + +## 6. 에러 코드 + +| Error Code | HTTP Status | 설명 | +|---|:---:|---| +| `COMMON_400` | `400` | 요청 파라미터가 잘못되었습니다. (예: `fcmToken`/`platform` 누락) | +| `USER_404` | `404` | 존재하지 않는 사용자입니다. | +| `NOTIFICATION_404` | `404` | 존재하지 않는 알림입니다. (본인 소유가 아닌 알림 포함) | diff --git a/src/main/java/com/swyp/picke/domain/battle/service/BattleServiceImpl.java b/src/main/java/com/swyp/picke/domain/battle/service/BattleServiceImpl.java index 8956fbcf..fb78140c 100644 --- a/src/main/java/com/swyp/picke/domain/battle/service/BattleServiceImpl.java +++ b/src/main/java/com/swyp/picke/domain/battle/service/BattleServiceImpl.java @@ -19,6 +19,7 @@ import com.swyp.picke.domain.battle.repository.BattleOptionTagRepository; import com.swyp.picke.domain.battle.repository.BattleRepository; import com.swyp.picke.domain.battle.repository.BattleTagRepository; +import com.swyp.picke.domain.notification.service.NotificationDispatchService; import com.swyp.picke.domain.scenario.entity.Scenario; import com.swyp.picke.domain.scenario.enums.ScenarioStatus; import com.swyp.picke.domain.scenario.repository.ScenarioRepository; @@ -82,6 +83,7 @@ public class BattleServiceImpl implements BattleService { private final BattleAutoSeedService battleAutoSeedService; private final ScenarioRepository scenarioRepository; private final ScenarioAudioPipelineService scenarioAudioPipelineService; + private final NotificationDispatchService notificationDispatchService; @Override public Battle findById(Long battleId) { @@ -517,6 +519,7 @@ public int openReadyBattles(LocalDateTime now) { publishBattleAssets(battle); battle.publish(); publishScenarioIfPresent(battle); + notifyNewBattleAfterCommit(battle); } openedCount += readyPage.getNumberOfElements(); @@ -576,6 +579,22 @@ private void publishScenarioIfPresent(Battle battle) { }); } + private void notifyNewBattleAfterCommit(Battle battle) { + Long battleId = battle.getId(); + String title = battle.getTitle(); + if (TransactionSynchronizationManager.isSynchronizationActive()) { + TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() { + @Override + public void afterCommit() { + notificationDispatchService.notifyNewBattle(battleId, title); + } + }); + return; + } + + notificationDispatchService.notifyNewBattle(battleId, title); + } + private void triggerScenarioAudioAfterCommit(Scenario scenario) { Long scenarioId = scenario.getId(); if (TransactionSynchronizationManager.isSynchronizationActive()) { diff --git a/src/main/java/com/swyp/picke/domain/notification/controller/DeviceController.java b/src/main/java/com/swyp/picke/domain/notification/controller/DeviceController.java new file mode 100644 index 00000000..3bbdf4ee --- /dev/null +++ b/src/main/java/com/swyp/picke/domain/notification/controller/DeviceController.java @@ -0,0 +1,45 @@ +package com.swyp.picke.domain.notification.controller; + +import com.swyp.picke.domain.notification.dto.request.RegisterDeviceRequest; +import com.swyp.picke.domain.notification.service.DeviceService; +import com.swyp.picke.global.common.response.ApiResponse; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; +import org.springframework.security.core.annotation.AuthenticationPrincipal; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +@Tag(name = "디바이스 API", description = "푸시 알림을 위한 디바이스 토큰 등록/해제 (Android: FCM 토큰, iOS: APNs 디바이스 토큰)") +@RestController +@RequiredArgsConstructor +@RequestMapping("/api/v1/devices") +public class DeviceController { + + private final DeviceService deviceService; + + @Operation(summary = "디바이스 푸시 토큰 등록", description = "로그인 또는 토큰 갱신 시 푸시 토큰을 등록합니다. Android는 FCM 토큰, iOS는 APNs 디바이스 토큰을 전달합니다.") + @PostMapping + public ApiResponse registerDevice( + @AuthenticationPrincipal Long userId, + @RequestBody @Valid RegisterDeviceRequest request + ) { + deviceService.registerDevice(userId, request); + return ApiResponse.onSuccess(null); + } + + @Operation(summary = "디바이스 푸시 토큰 해제", description = "로그아웃 시 푸시 토큰을 해제합니다.") + @DeleteMapping + public ApiResponse unregisterDevice( + @AuthenticationPrincipal Long userId, + @RequestParam String fcmToken + ) { + deviceService.unregisterDevice(userId, fcmToken); + return ApiResponse.onSuccess(null); + } +} diff --git a/src/main/java/com/swyp/picke/domain/notification/dto/request/RegisterDeviceRequest.java b/src/main/java/com/swyp/picke/domain/notification/dto/request/RegisterDeviceRequest.java new file mode 100644 index 00000000..2187db86 --- /dev/null +++ b/src/main/java/com/swyp/picke/domain/notification/dto/request/RegisterDeviceRequest.java @@ -0,0 +1,17 @@ +package com.swyp.picke.domain.notification.dto.request; + +import com.swyp.picke.domain.notification.enums.DevicePlatform; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; + +/** + * 푸시 토큰 등록 요청. + * platform=ANDROID이면 FCM 토큰, platform=IOS이면 APNs 디바이스 토큰을 fcmToken에 담아 전달한다. + */ +public record RegisterDeviceRequest( + @NotBlank + String fcmToken, + + @NotNull + DevicePlatform platform +) {} diff --git a/src/main/java/com/swyp/picke/domain/notification/dto/response/NotificationDetailResponse.java b/src/main/java/com/swyp/picke/domain/notification/dto/response/NotificationDetailResponse.java index 3dbbe826..dcadebb5 100644 --- a/src/main/java/com/swyp/picke/domain/notification/dto/response/NotificationDetailResponse.java +++ b/src/main/java/com/swyp/picke/domain/notification/dto/response/NotificationDetailResponse.java @@ -11,6 +11,7 @@ public record NotificationDetailResponse( String title, String body, Long referenceId, + Long perspectiveId, boolean isRead, LocalDateTime createdAt, LocalDateTime readAt diff --git a/src/main/java/com/swyp/picke/domain/notification/dto/response/NotificationSummaryResponse.java b/src/main/java/com/swyp/picke/domain/notification/dto/response/NotificationSummaryResponse.java index f03e0529..421c9659 100644 --- a/src/main/java/com/swyp/picke/domain/notification/dto/response/NotificationSummaryResponse.java +++ b/src/main/java/com/swyp/picke/domain/notification/dto/response/NotificationSummaryResponse.java @@ -11,6 +11,7 @@ public record NotificationSummaryResponse( String title, String body, Long referenceId, + Long perspectiveId, boolean isRead, LocalDateTime createdAt ) {} diff --git a/src/main/java/com/swyp/picke/domain/notification/entity/Notification.java b/src/main/java/com/swyp/picke/domain/notification/entity/Notification.java index a94c16c4..e3601400 100644 --- a/src/main/java/com/swyp/picke/domain/notification/entity/Notification.java +++ b/src/main/java/com/swyp/picke/domain/notification/entity/Notification.java @@ -46,6 +46,9 @@ public class Notification extends BaseEntity { @Column(name = "reference_id") private Long referenceId; + @Column(name = "perspective_id") + private Long perspectiveId; + @Column(name = "is_read", nullable = false) private boolean read; @@ -54,13 +57,14 @@ public class Notification extends BaseEntity { @Builder private Notification(User user, NotificationCategory category, NotificationDetailCode detailCode, - String title, String body, Long referenceId) { + String title, String body, Long referenceId, Long perspectiveId) { this.user = user; this.category = category; this.detailCode = detailCode; this.title = title; this.body = body; this.referenceId = referenceId; + this.perspectiveId = perspectiveId; this.read = false; } diff --git a/src/main/java/com/swyp/picke/domain/notification/entity/UserDevice.java b/src/main/java/com/swyp/picke/domain/notification/entity/UserDevice.java new file mode 100644 index 00000000..95b35c98 --- /dev/null +++ b/src/main/java/com/swyp/picke/domain/notification/entity/UserDevice.java @@ -0,0 +1,54 @@ +package com.swyp.picke.domain.notification.entity; + +import com.swyp.picke.domain.notification.enums.DevicePlatform; +import com.swyp.picke.domain.user.entity.User; +import com.swyp.picke.global.common.BaseEntity; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; +import jakarta.persistence.FetchType; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Table; +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.time.LocalDateTime; + +@Getter +@Entity +@Table(name = "user_devices") +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class UserDevice extends BaseEntity { + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "user_id", nullable = false) + private User user; + + @Column(name = "fcm_token", nullable = false, unique = true, length = 255) + private String fcmToken; + + @Enumerated(EnumType.STRING) + @Column(nullable = false, length = 10) + private DevicePlatform platform; + + @Column(name = "last_used_at", nullable = false) + private LocalDateTime lastUsedAt; + + @Builder + private UserDevice(User user, String fcmToken, DevicePlatform platform) { + this.user = user; + this.fcmToken = fcmToken; + this.platform = platform; + this.lastUsedAt = LocalDateTime.now(); + } + + public void reassign(User user, DevicePlatform platform) { + this.user = user; + this.platform = platform; + this.lastUsedAt = LocalDateTime.now(); + } +} diff --git a/src/main/java/com/swyp/picke/domain/notification/enums/DevicePlatform.java b/src/main/java/com/swyp/picke/domain/notification/enums/DevicePlatform.java new file mode 100644 index 00000000..5aff0ce6 --- /dev/null +++ b/src/main/java/com/swyp/picke/domain/notification/enums/DevicePlatform.java @@ -0,0 +1,6 @@ +package com.swyp.picke.domain.notification.enums; + +public enum DevicePlatform { + ANDROID, + IOS +} diff --git a/src/main/java/com/swyp/picke/domain/notification/enums/NotificationDetailCode.java b/src/main/java/com/swyp/picke/domain/notification/enums/NotificationDetailCode.java index 630e7283..8772897a 100644 --- a/src/main/java/com/swyp/picke/domain/notification/enums/NotificationDetailCode.java +++ b/src/main/java/com/swyp/picke/domain/notification/enums/NotificationDetailCode.java @@ -7,10 +7,12 @@ @RequiredArgsConstructor public enum NotificationDetailCode { - // CONTENT (1~3) + // CONTENT (1~3, 6~7) NEW_BATTLE(1, NotificationCategory.CONTENT, "새로운 배틀이 시작되었어요"), VOTE_RESULT(2, NotificationCategory.CONTENT, "투표 결과가 나왔어요"), CREDIT_EARNED(3, NotificationCategory.CONTENT, "포인트 적립"), + COMMENT_LIKE(6, NotificationCategory.CONTENT, "내 답글에 좋아요가 달렸어요"), + NEW_COMMENT(7, NotificationCategory.CONTENT, "내 답글에 댓글이 달렸어요"), // NOTICE (4) POLICY_CHANGE(4, NotificationCategory.NOTICE, "공지사항"), diff --git a/src/main/java/com/swyp/picke/domain/notification/repository/UserDeviceRepository.java b/src/main/java/com/swyp/picke/domain/notification/repository/UserDeviceRepository.java new file mode 100644 index 00000000..38a82933 --- /dev/null +++ b/src/main/java/com/swyp/picke/domain/notification/repository/UserDeviceRepository.java @@ -0,0 +1,19 @@ +package com.swyp.picke.domain.notification.repository; + +import com.swyp.picke.domain.notification.entity.UserDevice; +import com.swyp.picke.domain.notification.enums.DevicePlatform; + +import java.util.List; +import java.util.Optional; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface UserDeviceRepository extends JpaRepository { + + Optional findByFcmToken(String fcmToken); + + List findAllByUserId(Long userId); + + List findAllByUserIdAndPlatform(Long userId, DevicePlatform platform); + + void deleteByUserIdAndFcmToken(Long userId, String fcmToken); +} diff --git a/src/main/java/com/swyp/picke/domain/notification/service/DeviceService.java b/src/main/java/com/swyp/picke/domain/notification/service/DeviceService.java new file mode 100644 index 00000000..48e3467a --- /dev/null +++ b/src/main/java/com/swyp/picke/domain/notification/service/DeviceService.java @@ -0,0 +1,44 @@ +package com.swyp.picke.domain.notification.service; + +import com.swyp.picke.domain.notification.dto.request.RegisterDeviceRequest; +import com.swyp.picke.domain.notification.entity.UserDevice; +import com.swyp.picke.domain.notification.repository.UserDeviceRepository; +import com.swyp.picke.domain.user.entity.User; +import com.swyp.picke.domain.user.repository.UserRepository; +import com.swyp.picke.global.common.exception.CustomException; +import com.swyp.picke.global.common.exception.ErrorCode; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@RequiredArgsConstructor +@Transactional(readOnly = true) +public class DeviceService { + + private final UserDeviceRepository userDeviceRepository; + private final UserRepository userRepository; + + @Transactional + public void registerDevice(Long userId, RegisterDeviceRequest request) { + User user = userRepository.findById(userId) + .orElseThrow(() -> new CustomException(ErrorCode.USER_NOT_FOUND)); + + userDeviceRepository.findByFcmToken(request.fcmToken()) + .ifPresentOrElse( + device -> device.reassign(user, request.platform()), + () -> userDeviceRepository.save( + UserDevice.builder() + .user(user) + .fcmToken(request.fcmToken()) + .platform(request.platform()) + .build() + ) + ); + } + + @Transactional + public void unregisterDevice(Long userId, String fcmToken) { + userDeviceRepository.deleteByUserIdAndFcmToken(userId, fcmToken); + } +} diff --git a/src/main/java/com/swyp/picke/domain/notification/service/NotificationDispatchService.java b/src/main/java/com/swyp/picke/domain/notification/service/NotificationDispatchService.java new file mode 100644 index 00000000..b9ebd179 --- /dev/null +++ b/src/main/java/com/swyp/picke/domain/notification/service/NotificationDispatchService.java @@ -0,0 +1,95 @@ +package com.swyp.picke.domain.notification.service; + +import com.swyp.picke.domain.notification.entity.UserDevice; +import com.swyp.picke.domain.notification.enums.DevicePlatform; +import com.swyp.picke.domain.notification.enums.NotificationDetailCode; +import com.swyp.picke.domain.notification.repository.UserDeviceRepository; +import com.swyp.picke.global.infra.apns.service.ApnsPushService; +import com.swyp.picke.global.infra.fcm.service.FcmPushService; +import java.util.Map; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +/** + * 앱 내 알림(Notification)과 푸시를 함께 발송하는 알림 정책별 디스패치 서비스. + * Android는 FCM, iOS는 APNs로 직접 발송한다. + */ +@Service +@RequiredArgsConstructor +public class NotificationDispatchService { + + private final NotificationService notificationService; + private final UserDeviceRepository userDeviceRepository; + private final FcmPushService fcmPushService; + private final ApnsPushService apnsPushService; + + @Value("${picke.baseUrl}") + private String baseUrl; + + /** + * 새로운 배틀 발행 시 전체 사용자에게 인앱 broadcast 알림 + FCM 푸시를 발송한다. + */ + public void notifyNewBattle(Long battleId, String battleTitle) { + String body = "\"" + battleTitle + "\"에 지금 참여해보세요!"; + + notificationService.createBroadcastNotification(NotificationDetailCode.NEW_BATTLE, body, battleId); + + Map data = Map.of( + "type", "BATTLE", + "battleId", String.valueOf(battleId), + "url", baseUrl + "/battle/" + battleId + ); + + String pushTitle = NotificationDetailCode.NEW_BATTLE.getDefaultTitle(); + for (UserDevice device : userDeviceRepository.findAll()) { + sendPush(device, pushTitle, body, data); + } + } + + /** + * 내가 작성한 답글에 좋아요가 달렸을 때 답글 작성자에게 인앱 알림 + 푸시를 발송한다. + */ + public void notifyCommentLike(Long commentAuthorId, Long perspectiveId, Long commentId, String battleTitle) { + String body = "\"" + battleTitle + "\" 배틀에 남긴 내 답글에 좋아요가 달렸어요."; + + notificationService.createNotification( + commentAuthorId, NotificationDetailCode.COMMENT_LIKE, body, commentId, perspectiveId); + + sendCommentPush(commentAuthorId, NotificationDetailCode.COMMENT_LIKE, body, perspectiveId, commentId); + } + + /** + * 내가 작성한 글에 새로운 답글이 달렸을 때 글 작성자에게 인앱 알림 + 푸시를 발송한다. + */ + public void notifyNewComment(Long perspectiveAuthorId, Long perspectiveId, Long commentId, String battleTitle) { + String body = "\"" + battleTitle + "\" 배틀에 남긴 내 글에 새로운 답글이 달렸어요."; + + notificationService.createNotification( + perspectiveAuthorId, NotificationDetailCode.NEW_COMMENT, body, commentId, perspectiveId); + + sendCommentPush(perspectiveAuthorId, NotificationDetailCode.NEW_COMMENT, body, perspectiveId, commentId); + } + + private void sendCommentPush(Long userId, NotificationDetailCode detailCode, String body, Long perspectiveId, Long commentId) { + Map data = Map.of( + "type", "COMMENT", + "perspectiveId", String.valueOf(perspectiveId), + "commentId", String.valueOf(commentId), + "url", baseUrl + "/perspective/" + perspectiveId + "?commentId=" + commentId + ); + + String pushTitle = detailCode.getDefaultTitle(); + for (UserDevice device : userDeviceRepository.findAllByUserId(userId)) { + sendPush(device, pushTitle, body, data); + } + } + + private void sendPush(UserDevice device, String title, String body, Map data) { + if (device.getPlatform() == DevicePlatform.IOS) { + apnsPushService.send(device, title, body, data); + } else { + fcmPushService.send(device, title, body, data); + } + } +} diff --git a/src/main/java/com/swyp/picke/domain/notification/service/NotificationService.java b/src/main/java/com/swyp/picke/domain/notification/service/NotificationService.java index e8116e5b..1d5be4b5 100644 --- a/src/main/java/com/swyp/picke/domain/notification/service/NotificationService.java +++ b/src/main/java/com/swyp/picke/domain/notification/service/NotificationService.java @@ -36,6 +36,11 @@ public class NotificationService { @Transactional public Notification createNotification(Long userId, NotificationDetailCode detailCode, String body, Long referenceId) { + return createNotification(userId, detailCode, body, referenceId, null); + } + + @Transactional + public Notification createNotification(Long userId, NotificationDetailCode detailCode, String body, Long referenceId, Long perspectiveId) { User user = userRepository.findById(userId) .orElseThrow(() -> new CustomException(ErrorCode.USER_NOT_FOUND)); @@ -46,6 +51,7 @@ public Notification createNotification(Long userId, NotificationDetailCode detai .title(detailCode.getDefaultTitle()) .body(body) .referenceId(referenceId) + .perspectiveId(perspectiveId) .build(); return notificationRepository.save(notification); @@ -168,6 +174,7 @@ private NotificationDetailResponse toDetailResponse(Notification notification, b notification.getTitle(), notification.getBody(), notification.getReferenceId(), + notification.getPerspectiveId(), isRead, notification.getCreatedAt(), readAt @@ -182,6 +189,7 @@ private NotificationSummaryResponse toSummaryResponse(Notification notification, notification.getTitle(), notification.getBody(), notification.getReferenceId(), + notification.getPerspectiveId(), isRead, notification.getCreatedAt() ); diff --git a/src/main/java/com/swyp/picke/domain/perspective/service/CommentLikeService.java b/src/main/java/com/swyp/picke/domain/perspective/service/CommentLikeService.java index e1d49e3b..83ca5b6a 100644 --- a/src/main/java/com/swyp/picke/domain/perspective/service/CommentLikeService.java +++ b/src/main/java/com/swyp/picke/domain/perspective/service/CommentLikeService.java @@ -1,5 +1,6 @@ package com.swyp.picke.domain.perspective.service; +import com.swyp.picke.domain.notification.service.NotificationDispatchService; import com.swyp.picke.domain.perspective.dto.response.LikeResponse; import com.swyp.picke.domain.perspective.entity.CommentLike; import com.swyp.picke.domain.perspective.entity.PerspectiveComment; @@ -10,6 +11,8 @@ import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import org.springframework.transaction.support.TransactionSynchronization; +import org.springframework.transaction.support.TransactionSynchronizationManager; @Service @RequiredArgsConstructor @@ -18,6 +21,7 @@ public class CommentLikeService { private final PerspectiveCommentRepository commentRepository; private final CommentLikeRepository commentLikeRepository; + private final NotificationDispatchService notificationDispatchService; @Transactional public LikeResponse addLike(Long commentId, Long userId) { @@ -37,9 +41,30 @@ public LikeResponse addLike(Long commentId, Long userId) { .build()); comment.incrementLikeCount(); + notifyCommentLikeAfterCommit(comment); + return new LikeResponse(comment.getId(), comment.getLikeCount(), true); } + private void notifyCommentLikeAfterCommit(PerspectiveComment comment) { + Long commentId = comment.getId(); + Long commentAuthorId = comment.getUser().getId(); + Long perspectiveId = comment.getPerspective().getId(); + String battleTitle = comment.getPerspective().getBattle().getTitle(); + + if (TransactionSynchronizationManager.isSynchronizationActive()) { + TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() { + @Override + public void afterCommit() { + notificationDispatchService.notifyCommentLike(commentAuthorId, perspectiveId, commentId, battleTitle); + } + }); + return; + } + + notificationDispatchService.notifyCommentLike(commentAuthorId, perspectiveId, commentId, battleTitle); + } + @Transactional public LikeResponse removeLike(Long commentId, Long userId) { PerspectiveComment comment = findCommentById(commentId); diff --git a/src/main/java/com/swyp/picke/domain/perspective/service/PerspectiveCommentService.java b/src/main/java/com/swyp/picke/domain/perspective/service/PerspectiveCommentService.java index 9551185f..36964ad7 100644 --- a/src/main/java/com/swyp/picke/domain/perspective/service/PerspectiveCommentService.java +++ b/src/main/java/com/swyp/picke/domain/perspective/service/PerspectiveCommentService.java @@ -3,6 +3,7 @@ import com.swyp.picke.domain.battle.entity.BattleOption; import com.swyp.picke.domain.battle.service.BattleService; import com.swyp.picke.domain.battle.util.BattleOptionDisplay; +import com.swyp.picke.domain.notification.service.NotificationDispatchService; import com.swyp.picke.domain.perspective.dto.request.CreateCommentRequest; import com.swyp.picke.domain.perspective.dto.request.UpdateCommentRequest; import com.swyp.picke.domain.perspective.dto.response.CommentListResponse; @@ -26,6 +27,8 @@ import org.springframework.data.domain.PageRequest; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import org.springframework.transaction.support.TransactionSynchronization; +import org.springframework.transaction.support.TransactionSynchronizationManager; import java.time.LocalDateTime; import java.util.List; @@ -45,6 +48,7 @@ public class PerspectiveCommentService { private final BattleVoteService BattleVoteService; private final BattleService battleService; private final S3PresignedUrlService s3PresignedUrlService; + private final NotificationDispatchService notificationDispatchService; @Transactional public CreateCommentResponse createComment(Long perspectiveId, Long userId, CreateCommentRequest request) { @@ -61,6 +65,8 @@ public CreateCommentResponse createComment(Long perspectiveId, Long userId, Crea commentRepository.save(comment); perspective.incrementCommentCount(); + notifyNewCommentAfterCommit(comment, perspective, userId); + UserSummary userSummary = userQueryService.findSummaryById(userId); String characterImageUrl = resolveCharacterImageUrl(userSummary.characterType()); Long postVoteOptionId = BattleVoteService.findPostVoteOptionId(perspective.getBattle().getId(), userId); @@ -80,6 +86,29 @@ public CreateCommentResponse createComment(Long perspectiveId, Long userId, Crea ); } + private void notifyNewCommentAfterCommit(PerspectiveComment comment, Perspective perspective, Long commenterId) { + Long perspectiveAuthorId = perspective.getUser().getId(); + if (perspectiveAuthorId.equals(commenterId)) { + return; + } + + Long commentId = comment.getId(); + Long perspectiveId = perspective.getId(); + String battleTitle = perspective.getBattle().getTitle(); + + if (TransactionSynchronizationManager.isSynchronizationActive()) { + TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() { + @Override + public void afterCommit() { + notificationDispatchService.notifyNewComment(perspectiveAuthorId, perspectiveId, commentId, battleTitle); + } + }); + return; + } + + notificationDispatchService.notifyNewComment(perspectiveAuthorId, perspectiveId, commentId, battleTitle); + } + public CommentListResponse getComments(Long perspectiveId, Long userId, String cursor, Integer size) { Perspective perspective = findPerspectiveById(perspectiveId); diff --git a/src/main/java/com/swyp/picke/domain/user/service/CreditService.java b/src/main/java/com/swyp/picke/domain/user/service/CreditService.java index bab5b81c..82c8359c 100644 --- a/src/main/java/com/swyp/picke/domain/user/service/CreditService.java +++ b/src/main/java/com/swyp/picke/domain/user/service/CreditService.java @@ -1,5 +1,9 @@ package com.swyp.picke.domain.user.service; +import com.swyp.picke.domain.battle.entity.Battle; +import com.swyp.picke.domain.battle.repository.BattleRepository; +import com.swyp.picke.domain.notification.enums.NotificationDetailCode; +import com.swyp.picke.domain.notification.service.NotificationService; import com.swyp.picke.domain.user.entity.CreditHistory; import com.swyp.picke.domain.user.enums.TierCode; import com.swyp.picke.domain.user.entity.User; @@ -23,6 +27,8 @@ public class CreditService { private final CreditHistoryRepository creditHistoryRepository; private final UserRepository userRepository; private final UserService userService; + private final NotificationService notificationService; + private final BattleRepository battleRepository; /** * 현재 로그인한 유저에게 크레딧 적립 (기본 포인트). @@ -86,6 +92,12 @@ public void addCredit(Long userId, CreditType creditType, int amount, Long refer } throw new CustomException(ErrorCode.USER_NOT_FOUND); } + + if (amount > 0) { + notificationService.createNotification( + userId, NotificationDetailCode.CREDIT_EARNED, buildCreditEarnedMessage(creditType, amount, referenceId), referenceId + ); + } } /** @@ -117,6 +129,26 @@ private void validateReferenceId(Long referenceId) { } } + /** + * 적립 타입별 CREDIT_EARNED 인앱 알림 문구 생성. + * MAJORITY_WIN은 referenceId(=battleId)로 배틀 제목을 조회해 문구에 포함한다. + */ + private String buildCreditEarnedMessage(CreditType creditType, int amount, Long referenceId) { + return switch (creditType) { + case DEFAULT_CREDIT -> "픽케에 오신 걸 환영해요! 가입 보너스 +" + amount + "P"; + case TODAY_CREDIT -> "일일 무료 포인트 +" + amount + " 충전되었어요."; + case MAJORITY_WIN -> buildMajorityWinMessage(referenceId, amount); + default -> "포인트 +" + amount + "P가 적립되었어요."; + }; + } + + private String buildMajorityWinMessage(Long battleId, int amount) { + String title = battleRepository.findById(battleId) + .map(Battle::getTitle) + .orElse("배틀"); + return "\"" + title + "\"에서 다수결과 같은 선택을 했어요! +" + amount + "P"; + } + /** * 크레딧 적립/소비 기록 조회 */ diff --git a/src/main/java/com/swyp/picke/global/config/ApnsConfig.java b/src/main/java/com/swyp/picke/global/config/ApnsConfig.java new file mode 100644 index 00000000..22323e03 --- /dev/null +++ b/src/main/java/com/swyp/picke/global/config/ApnsConfig.java @@ -0,0 +1,77 @@ +package com.swyp.picke.global.config; + +import com.eatthepath.pushy.apns.ApnsClient; +import com.eatthepath.pushy.apns.ApnsClientBuilder; +import com.eatthepath.pushy.apns.auth.ApnsSigningKey; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import software.amazon.awssdk.services.s3.S3Client; +import software.amazon.awssdk.services.s3.model.GetObjectRequest; + +import java.io.File; +import java.nio.file.Files; +import java.nio.file.Path; + +/** + * 다이렉트 APNs(Apple Push Notification service) 클라이언트 설정. + * apns.enabled=true 일 때만 빈을 생성하며, 비활성화 시 ApnsPushService가 발송을 건너뛴다. + * 컨테이너 배포 환경(Railway 등)은 영구 파일시스템이 없으므로, + * S3에 업로드해둔 .p8 키(APNS_CREDENTIALS_S3_KEY)를 임시 파일로 받아 사용하고, + * 없으면 로컬 개발 환경의 파일 경로(APNS_CREDENTIALS_PATH)를 사용한다. + */ +@Configuration +@ConditionalOnProperty(prefix = "apns", name = "enabled", havingValue = "true") +@RequiredArgsConstructor +public class ApnsConfig { + + private final S3Client s3Client; + + @Value("${spring.cloud.aws.s3.bucket}") + private String bucketName; + + @Value("${apns.credentials.s3-key:}") + private String credentialsS3Key; + + @Value("${apns.credentials.location:}") + private String credentialsLocation; + + @Value("${apns.key-id}") + private String keyId; + + @Value("${apns.team-id}") + private String teamId; + + @Value("${apns.production}") + private boolean production; + + @Bean(destroyMethod = "close") + public ApnsClient apnsClient() throws Exception { + ApnsSigningKey signingKey = ApnsSigningKey.loadFromPkcs8File( + resolveCredentialsFile(), teamId, keyId); + + return new ApnsClientBuilder() + .setApnsServer(production + ? ApnsClientBuilder.PRODUCTION_APNS_HOST + : ApnsClientBuilder.DEVELOPMENT_APNS_HOST) + .setSigningKey(signingKey) + .build(); + } + + private File resolveCredentialsFile() throws Exception { + if (!credentialsS3Key.isBlank()) { + GetObjectRequest request = GetObjectRequest.builder() + .bucket(bucketName) + .key(credentialsS3Key) + .build(); + + Path tempFile = Files.createTempFile("apns-key", ".p8"); + tempFile.toFile().deleteOnExit(); + s3Client.getObject(request, tempFile); + return tempFile.toFile(); + } + return new File(credentialsLocation); + } +} diff --git a/src/main/java/com/swyp/picke/global/config/FirebaseConfig.java b/src/main/java/com/swyp/picke/global/config/FirebaseConfig.java new file mode 100644 index 00000000..29f784ab --- /dev/null +++ b/src/main/java/com/swyp/picke/global/config/FirebaseConfig.java @@ -0,0 +1,61 @@ +package com.swyp.picke.global.config; + +import com.google.auth.oauth2.GoogleCredentials; +import com.google.firebase.FirebaseApp; +import com.google.firebase.FirebaseOptions; +import com.google.firebase.messaging.FirebaseMessaging; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import software.amazon.awssdk.services.s3.S3Client; +import software.amazon.awssdk.services.s3.model.GetObjectRequest; + +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; + +/** + * 컨테이너 배포 환경(Railway 등)은 영구 파일시스템이 없으므로, + * S3에 업로드해둔 서비스 계정 JSON(FCM_CREDENTIALS_S3_KEY)을 우선 사용하고, + * 없으면 로컬 개발 환경의 파일 경로(FCM_CREDENTIALS_PATH)를 사용한다. + */ +@Configuration +@RequiredArgsConstructor +public class FirebaseConfig { + + private final S3Client s3Client; + + @Value("${spring.cloud.aws.s3.bucket}") + private String bucketName; + + @Value("${firebase.credentials.s3-key:}") + private String credentialsS3Key; + + @Value("${firebase.credentials.location:}") + private String credentialsLocation; + + @Bean + public FirebaseMessaging firebaseMessaging() throws IOException { + FirebaseOptions options = FirebaseOptions.builder() + .setCredentials(GoogleCredentials.fromStream(loadCredentials())) + .build(); + + FirebaseApp firebaseApp = FirebaseApp.getApps().isEmpty() + ? FirebaseApp.initializeApp(options) + : FirebaseApp.getInstance(); + + return FirebaseMessaging.getInstance(firebaseApp); + } + + private InputStream loadCredentials() throws IOException { + if (!credentialsS3Key.isBlank()) { + GetObjectRequest request = GetObjectRequest.builder() + .bucket(bucketName) + .key(credentialsS3Key) + .build(); + return s3Client.getObject(request); + } + return new FileInputStream(credentialsLocation); + } +} diff --git a/src/main/java/com/swyp/picke/global/infra/apns/service/ApnsPushService.java b/src/main/java/com/swyp/picke/global/infra/apns/service/ApnsPushService.java new file mode 100644 index 00000000..01339477 --- /dev/null +++ b/src/main/java/com/swyp/picke/global/infra/apns/service/ApnsPushService.java @@ -0,0 +1,75 @@ +package com.swyp.picke.global.infra.apns.service; + +import com.eatthepath.pushy.apns.ApnsClient; +import com.eatthepath.pushy.apns.PushNotificationResponse; +import com.eatthepath.pushy.apns.util.ApnsPayloadBuilder; +import com.eatthepath.pushy.apns.util.SimpleApnsPayloadBuilder; +import com.eatthepath.pushy.apns.util.SimpleApnsPushNotification; +import com.eatthepath.pushy.apns.util.TokenUtil; +import com.swyp.picke.domain.notification.entity.UserDevice; +import com.swyp.picke.domain.notification.repository.UserDeviceRepository; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +import java.util.Map; +import java.util.Optional; +import java.util.Set; + +/** + * iOS 디바이스에 FCM을 거치지 않고 APNs로 직접 푸시를 발송한다. + * apns.enabled=false(미설정)인 환경에서는 ApnsClient 빈이 없으므로 발송을 건너뛴다. + */ +@Slf4j +@Service +@RequiredArgsConstructor +public class ApnsPushService { + + private static final Set INVALID_TOKEN_REASONS = Set.of( + "BadDeviceToken", "Unregistered", "DeviceTokenNotForTopic"); + + private final Optional apnsClient; + private final UserDeviceRepository userDeviceRepository; + + @Value("${apns.bundle-id}") + private String bundleId; + + public void send(UserDevice device, String title, String body, Map data) { + if (apnsClient.isEmpty()) { + log.warn("APNs가 설정되지 않아 푸시를 건너뜁니다. deviceId={}", device.getId()); + return; + } + + ApnsPayloadBuilder payloadBuilder = new SimpleApnsPayloadBuilder() + .setAlertTitle(title) + .setAlertBody(body) + .setSound("default"); + data.forEach(payloadBuilder::addCustomProperty); + + String token = TokenUtil.sanitizeTokenString(device.getFcmToken()); + SimpleApnsPushNotification notification = + new SimpleApnsPushNotification(token, bundleId, payloadBuilder.build()); + + apnsClient.get().sendNotification(notification).whenComplete((response, cause) -> { + if (cause != null) { + log.warn("APNs 푸시 전송 실패. deviceId={}, error={}", device.getId(), cause.getMessage()); + return; + } + handleResponse(device, response); + }); + } + + private void handleResponse(UserDevice device, PushNotificationResponse response) { + if (response.isAccepted()) { + return; + } + + String reason = response.getRejectionReason().orElse("UNKNOWN"); + log.warn("APNs 푸시 거부됨. deviceId={}, reason={}", device.getId(), reason); + + if (INVALID_TOKEN_REASONS.contains(reason)) { + userDeviceRepository.deleteById(device.getId()); + } + } +} diff --git a/src/main/java/com/swyp/picke/global/infra/fcm/service/FcmPushService.java b/src/main/java/com/swyp/picke/global/infra/fcm/service/FcmPushService.java new file mode 100644 index 00000000..1f836b98 --- /dev/null +++ b/src/main/java/com/swyp/picke/global/infra/fcm/service/FcmPushService.java @@ -0,0 +1,40 @@ +package com.swyp.picke.global.infra.fcm.service; + +import com.google.firebase.messaging.AndroidConfig; +import com.google.firebase.messaging.FirebaseMessaging; +import com.google.firebase.messaging.FirebaseMessagingException; +import com.google.firebase.messaging.Message; +import com.swyp.picke.domain.notification.entity.UserDevice; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.util.Map; + +@Slf4j +@Service +@RequiredArgsConstructor +public class FcmPushService { + + private final FirebaseMessaging firebaseMessaging; + + /** + * Android 디바이스에 FCM data-only 메시지를 발송한다. + * iOS는 FCM을 거치지 않고 ApnsPushService가 APNs로 직접 발송한다. + */ + public void send(UserDevice device, String title, String body, Map data) { + Message message = Message.builder() + .setToken(device.getFcmToken()) + .putAllData(data) + .setAndroidConfig(AndroidConfig.builder() + .setPriority(AndroidConfig.Priority.HIGH) + .build()) + .build(); + + try { + firebaseMessaging.send(message); + } catch (FirebaseMessagingException e) { + log.warn("FCM 푸시 전송 실패. deviceId={}, error={}", device.getId(), e.getMessage()); + } + } +} diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 2ca8d949..447d5f29 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -41,6 +41,23 @@ spring: credentials: location: ${GCP_CREDENTIALS_PATH} +# 3-1. Firebase Admin SDK (FCM 푸시 알림 - Android) +firebase: + credentials: + location: ${FCM_CREDENTIALS_PATH:} + s3-key: ${FCM_CREDENTIALS_S3_KEY:} + +# 3-2. APNs (다이렉트 APNs 푸시 알림 - iOS) +apns: + enabled: ${APNS_ENABLED:false} + credentials: + location: ${APNS_CREDENTIALS_PATH:} + s3-key: ${APNS_CREDENTIALS_S3_KEY:} + key-id: ${APNS_KEY_ID:} + team-id: ${APNS_TEAM_ID:${APPLE_TEAM_ID:}} + bundle-id: ${APNS_BUNDLE_ID:} + production: ${APNS_PRODUCTION:false} + # 4. 인증 및 보안 설정 (OAuth2, JWT) oauth: kakao: From b5a681b86251ba136663632232654519bf03c2df Mon Sep 17 00:00:00 2001 From: HYH0804 Date: Fri, 12 Jun 2026 00:12:30 +0900 Subject: [PATCH 07/29] =?UTF-8?q?#262=20[Fix]=20APNs=20=EC=9E=90=EA=B2=A9?= =?UTF-8?q?=EC=A6=9D=EB=AA=85=20S3=20=EB=8B=A4=EC=9A=B4=EB=A1=9C=EB=93=9C?= =?UTF-8?q?=20=EC=8B=9C=20=EC=9E=84=EC=8B=9C=ED=8C=8C=EC=9D=BC=20=EC=B6=A9?= =?UTF-8?q?=EB=8F=8C=20=EC=98=A4=EB=A5=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit createTempFile로 생성된 빈 파일이 이미 존재해 S3 getObject의 toFile 다운로드가 FileAlreadyExistsException으로 실패하던 문제 수정 --- src/main/java/com/swyp/picke/global/config/ApnsConfig.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/com/swyp/picke/global/config/ApnsConfig.java b/src/main/java/com/swyp/picke/global/config/ApnsConfig.java index 22323e03..652d3204 100644 --- a/src/main/java/com/swyp/picke/global/config/ApnsConfig.java +++ b/src/main/java/com/swyp/picke/global/config/ApnsConfig.java @@ -68,6 +68,7 @@ private File resolveCredentialsFile() throws Exception { .build(); Path tempFile = Files.createTempFile("apns-key", ".p8"); + Files.delete(tempFile); tempFile.toFile().deleteOnExit(); s3Client.getObject(request, tempFile); return tempFile.toFile(); From d281fa31e26ba371fae58c8e597114a5be4011d4 Mon Sep 17 00:00:00 2001 From: Youwol <153346797+si-zero@users.noreply.github.com> Date: Fri, 12 Jun 2026 01:28:15 +0900 Subject: [PATCH 08/29] =?UTF-8?q?#264=20[Fix]=20AdMob=20SSV=20=ED=8F=AC?= =?UTF-8?q?=EC=9D=B8=ED=8A=B8=20=EB=AF=B8=EC=A0=81=EB=A6=BD=20=EB=B2=84?= =?UTF-8?q?=EA=B7=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/AdMobRewardServiceImpl.java | 36 +++++++++---------- 1 file changed, 16 insertions(+), 20 deletions(-) diff --git a/src/main/java/com/swyp/picke/domain/reward/service/AdMobRewardServiceImpl.java b/src/main/java/com/swyp/picke/domain/reward/service/AdMobRewardServiceImpl.java index 6f8b9931..b77bb946 100644 --- a/src/main/java/com/swyp/picke/domain/reward/service/AdMobRewardServiceImpl.java +++ b/src/main/java/com/swyp/picke/domain/reward/service/AdMobRewardServiceImpl.java @@ -30,48 +30,44 @@ public class AdMobRewardServiceImpl implements AdMobRewardService { @Override @Transactional public String processReward(AdMobRewardRequest request) { + log.info("[AdMob] SSV 처리 시작: transaction_id={}, userTag={}, reward_amount={}, ad_unit={}", + request.transaction_id(), request.getUserTag(), request.reward_amount(), request.ad_unit()); + // 1. 서명 검증 (공식 파라미터 기반) /*if (!verifyAdMobSignature(request)) { - log.warn("AdMob 서명 검증 실패: transaction_id={}", request.transaction_id()); + log.warn("[AdMob] 서명 검증 실패: transaction_id={}", request.transaction_id()); throw new CustomException(ErrorCode.REWARD_INVALID_SIGNATURE); }*/ // 2. 중복 처리 방지 if (adRewardHistoryRepository.existsByTransactionId(request.transaction_id())) { - log.info("이미 처리된 광고 요청입니다: transaction_id={}", request.transaction_id()); + log.info("[AdMob] 이미 처리된 요청: transaction_id={}", request.transaction_id()); return "Already Processed"; } - // 3. 유저 확인 (UserTag를 이용해 UserService에서 실제 유저 확보) - // request.getUserTag()는 custom_data 혹은 user_id를 반환합니다. + // 3. 유저 확인 (custom_data → user_id 순으로 조회) + log.info("[AdMob] 유저 조회 시도: userTag={}", request.getUserTag()); User user = userService.findByUserTag(request.getUserTag()); + log.info("[AdMob] 유저 확인 완료: userId={}", user.getId()); - // 4. 보상 이력(AdRewardHistory) 저장 + // 4. 보상 이력 저장 후 즉시 id 확보 (saveAndFlush) AdRewardHistory history = AdRewardHistory.builder() .transactionId(request.transaction_id()) .user(user) .rewardAmount(request.reward_amount()) - .rewardItem(request.getRewardType()) // // Enum 명칭 저장 + .rewardItem(request.getRewardType()) .build(); - adRewardHistoryRepository.save(history); + adRewardHistoryRepository.saveAndFlush(history); + log.info("[AdMob] 보상 이력 저장 완료: historyId={}", history.getId()); - // // 5. 크레딧 적립 - Long refId = parseTransactionId(request.transaction_id()); - creditService.addCredit(user.getId(), CreditType.FREE_CHARGE, request.reward_amount(), refId); + // 5. 크레딧 적립 (history.getId()를 referenceId로 사용해 unique 충돌 방지) + creditService.addCredit(user.getId(), CreditType.FREE_CHARGE, request.reward_amount(), history.getId()); + log.info("[AdMob] 포인트 적립 완료: userId={}, amount={}, historyId={}", + user.getId(), request.reward_amount(), history.getId()); - log.info("보상 지급 완료: userTag={}, userId={}, amount={}", - user.getUserTag(), user.getId(), request.reward_amount()); return "OK"; } - private Long parseTransactionId(String transactionId) { - try { - return Long.parseLong(transactionId.replaceAll("[^0-9]", "")); - } catch (Exception e) { - return (long) Math.abs(transactionId.hashCode()); - } - } - /** * // 6. 서명 검증 로직 수정 * 구글 공식 문서의 파라미터 순서와 명칭(ad_unit 등)을 엄격히 준수해야 합니다. From 968d6a3582e72efea2775b0368bf5ccc4cc0a917 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A4=80=ED=98=81?= <127603139+HYH0804@users.noreply.github.com> Date: Sun, 14 Jun 2026 17:11:13 +0900 Subject: [PATCH 09/29] #262 merge (#266) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## #️ 연관된 이슈 - #262 ## 📝 작업 내용 ### ✨ Feat | 내용 | 파일 | |------|------| | 새 배틀/답글 좋아요/새 댓글/관리자 공지·이벤트 알림 발송 시 UserSettings의 ON/OFF 설정을 확인해 OFF인 사용자에게는 푸시를 보내지 않도록 분기 (인앱 알림은 항상 생성) | `NotificationDispatchService.java`, `UserSettingsRepository.java`, `UserDeviceRepository.java`, `AdminNotificationService.java` | | 오늘의 픽으로 자동 배정된 배틀에도 새 배틀 알림(인앱+푸시) 발송 추가 | `BattleServiceImpl.java` | ### 🐛 Fix | 내용 | 파일 | |------|------| | 관점/댓글 삭제 시 좋아요·신고 잔여 데이터가 남아 FK 제약 조건 위반 오류가 발생하던 문제 수정 | `PerspectiveService.java`, `PerspectiveCommentService.java`, `CommentLikeRepository.java`, `CommentReportRepository.java`, `PerspectiveCommentRepository.java`, `PerspectiveLikeRepository.java`, `PerspectiveReportRepository.java` | ## 📌 공유 사항 > 1. 알림 ON/OFF 설정 매핑은 다음과 같습니다. > - `newBattleEnabled` → 새 배틀 알림 > - `contentLikeEnabled` → 좋아요 알림 > - `newCommentEnabled` → 새 댓글 알림 > - `marketingEventEnabled` → 이벤트 및 소식 알림 (공지/이벤트) > - `commentReplyEnabled`, `battleResultEnabled` → 현재 매핑되는 알림 이벤트가 없어 보류 (정책 미정) > 2. OFF 상태여도 인앱 Notification은 항상 생성되고, 푸시 발송만 차단됩니다. UserSettings가 없는 레거시 유저는 기본값 ON으로 처리됩니다. ## ✅ 체크리스트 - [x] Reviewer에 팀원들을 선택했나요? - [x] Assignees에 본인을 선택했나요? - [x] 컨벤션에 맞는 Type을 선택했나요? - [x] Development에 이슈를 연동했나요? - [x] Merge 하려는 브랜치가 올바르게 설정되어 있나요? - [x] 컨벤션을 지키고 있나요? - [x] 로컬에서 실행했을 때 에러가 발생하지 않나요? - [x] 팀원들에게 PR 링크 공유를 했나요? ## 📸 스크린샷 ## 💬 리뷰 요구사항 > 1. 관리자 공지/이벤트 알림(POLICY_CHANGE/PROMOTION)을 `marketingEventEnabled` 하나로 묶어서 게이팅했는데, 이 매핑이 적절한지 의견 부탁드립니다. --------- Co-authored-by: Claude Sonnet 4.6 --- .../service/AdminNotificationService.java | 8 ++++ .../battle/service/BattleServiceImpl.java | 1 + .../repository/UserDeviceRepository.java | 2 + .../service/NotificationDispatchService.java | 38 +++++++++++++++++-- .../repository/CommentLikeRepository.java | 5 +++ .../repository/CommentReportRepository.java | 6 +++ .../PerspectiveCommentRepository.java | 2 + .../repository/PerspectiveLikeRepository.java | 2 + .../PerspectiveReportRepository.java | 2 + .../service/PerspectiveCommentService.java | 4 ++ .../service/PerspectiveService.java | 16 ++++++++ .../repository/UserSettingsRepository.java | 8 ++++ 12 files changed, 91 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/swyp/picke/domain/admin/service/AdminNotificationService.java b/src/main/java/com/swyp/picke/domain/admin/service/AdminNotificationService.java index d131e75b..c5f66053 100644 --- a/src/main/java/com/swyp/picke/domain/admin/service/AdminNotificationService.java +++ b/src/main/java/com/swyp/picke/domain/admin/service/AdminNotificationService.java @@ -8,6 +8,7 @@ import com.swyp.picke.domain.notification.enums.NotificationCategory; import com.swyp.picke.domain.notification.enums.NotificationDetailCode; import com.swyp.picke.domain.notification.repository.NotificationRepository; +import com.swyp.picke.domain.notification.service.NotificationDispatchService; import com.swyp.picke.domain.notification.service.NotificationService; import com.swyp.picke.global.common.exception.CustomException; import com.swyp.picke.global.common.exception.ErrorCode; @@ -25,6 +26,7 @@ public class AdminNotificationService { private static final int DEFAULT_PAGE_SIZE = 20; private final NotificationService notificationService; + private final NotificationDispatchService notificationDispatchService; private final NotificationRepository notificationRepository; @Transactional @@ -36,6 +38,12 @@ public AdminNoticeDetailResponse createNotice(AdminNoticeCreateRequest request) request.body(), null ); + + if (detailCode.getCategory() == NotificationCategory.NOTICE + || detailCode.getCategory() == NotificationCategory.EVENT) { + notificationDispatchService.notifyAdminNotice(detailCode, request.title(), request.body()); + } + return toDetailResponse(notification); } diff --git a/src/main/java/com/swyp/picke/domain/battle/service/BattleServiceImpl.java b/src/main/java/com/swyp/picke/domain/battle/service/BattleServiceImpl.java index fb78140c..6c661817 100644 --- a/src/main/java/com/swyp/picke/domain/battle/service/BattleServiceImpl.java +++ b/src/main/java/com/swyp/picke/domain/battle/service/BattleServiceImpl.java @@ -219,6 +219,7 @@ private void ensureTodayPicks(LocalDate today, int requiredCount) { List candidates = battleRepository.findAutoAssignableTodayPicks(today, PageRequest.of(0, missingCount)); for (Battle candidate : candidates) { candidate.updateTargetDate(today); + notifyNewBattleAfterCommit(candidate); } } diff --git a/src/main/java/com/swyp/picke/domain/notification/repository/UserDeviceRepository.java b/src/main/java/com/swyp/picke/domain/notification/repository/UserDeviceRepository.java index 38a82933..e6f3869a 100644 --- a/src/main/java/com/swyp/picke/domain/notification/repository/UserDeviceRepository.java +++ b/src/main/java/com/swyp/picke/domain/notification/repository/UserDeviceRepository.java @@ -13,6 +13,8 @@ public interface UserDeviceRepository extends JpaRepository { List findAllByUserId(Long userId); + List findAllByUserIdIn(List userIds); + List findAllByUserIdAndPlatform(Long userId, DevicePlatform platform); void deleteByUserIdAndFcmToken(Long userId, String fcmToken); diff --git a/src/main/java/com/swyp/picke/domain/notification/service/NotificationDispatchService.java b/src/main/java/com/swyp/picke/domain/notification/service/NotificationDispatchService.java index b9ebd179..78c1f367 100644 --- a/src/main/java/com/swyp/picke/domain/notification/service/NotificationDispatchService.java +++ b/src/main/java/com/swyp/picke/domain/notification/service/NotificationDispatchService.java @@ -4,9 +4,13 @@ import com.swyp.picke.domain.notification.enums.DevicePlatform; import com.swyp.picke.domain.notification.enums.NotificationDetailCode; import com.swyp.picke.domain.notification.repository.UserDeviceRepository; +import com.swyp.picke.domain.user.entity.UserSettings; +import com.swyp.picke.domain.user.repository.UserSettingsRepository; import com.swyp.picke.global.infra.apns.service.ApnsPushService; import com.swyp.picke.global.infra.fcm.service.FcmPushService; +import java.util.List; import java.util.Map; +import java.util.function.Predicate; import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; @@ -14,6 +18,7 @@ /** * 앱 내 알림(Notification)과 푸시를 함께 발송하는 알림 정책별 디스패치 서비스. * Android는 FCM, iOS는 APNs로 직접 발송한다. + * 인앱 알림은 항상 생성되며, 푸시 발송 여부만 {@link UserSettings}의 알림 ON/OFF 설정을 따른다. */ @Service @RequiredArgsConstructor @@ -21,6 +26,7 @@ public class NotificationDispatchService { private final NotificationService notificationService; private final UserDeviceRepository userDeviceRepository; + private final UserSettingsRepository userSettingsRepository; private final FcmPushService fcmPushService; private final ApnsPushService apnsPushService; @@ -42,7 +48,8 @@ public void notifyNewBattle(Long battleId, String battleTitle) { ); String pushTitle = NotificationDetailCode.NEW_BATTLE.getDefaultTitle(); - for (UserDevice device : userDeviceRepository.findAll()) { + List userIds = userSettingsRepository.findUserIdsByNewBattleEnabledTrue(); + for (UserDevice device : userDeviceRepository.findAllByUserIdIn(userIds)) { sendPush(device, pushTitle, body, data); } } @@ -56,7 +63,9 @@ public void notifyCommentLike(Long commentAuthorId, Long perspectiveId, Long com notificationService.createNotification( commentAuthorId, NotificationDetailCode.COMMENT_LIKE, body, commentId, perspectiveId); - sendCommentPush(commentAuthorId, NotificationDetailCode.COMMENT_LIKE, body, perspectiveId, commentId); + if (isPushEnabled(commentAuthorId, UserSettings::isContentLikeEnabled)) { + sendCommentPush(commentAuthorId, NotificationDetailCode.COMMENT_LIKE, body, perspectiveId, commentId); + } } /** @@ -68,7 +77,30 @@ public void notifyNewComment(Long perspectiveAuthorId, Long perspectiveId, Long notificationService.createNotification( perspectiveAuthorId, NotificationDetailCode.NEW_COMMENT, body, commentId, perspectiveId); - sendCommentPush(perspectiveAuthorId, NotificationDetailCode.NEW_COMMENT, body, perspectiveId, commentId); + if (isPushEnabled(perspectiveAuthorId, UserSettings::isNewCommentEnabled)) { + sendCommentPush(perspectiveAuthorId, NotificationDetailCode.NEW_COMMENT, body, perspectiveId, commentId); + } + } + + /** + * 관리자가 등록한 공지/이벤트 알림에 대해 '이벤트 및 소식 알림' 설정이 ON인 사용자에게 푸시를 발송한다. + */ + public void notifyAdminNotice(NotificationDetailCode detailCode, String title, String body) { + Map data = Map.of("type", detailCode.getCategory().name()); + + List userIds = userSettingsRepository.findUserIdsByMarketingEventEnabledTrue(); + for (UserDevice device : userDeviceRepository.findAllByUserIdIn(userIds)) { + sendPush(device, title, body, data); + } + } + + /** + * 유저의 알림 ON/OFF 설정을 확인한다. 설정이 없는 경우(레거시 유저 등) 기본값은 true. + */ + private boolean isPushEnabled(Long userId, Predicate condition) { + return userSettingsRepository.findByUserId(userId) + .map(condition::test) + .orElse(true); } private void sendCommentPush(Long userId, NotificationDetailCode detailCode, String body, Long perspectiveId, Long commentId) { diff --git a/src/main/java/com/swyp/picke/domain/perspective/repository/CommentLikeRepository.java b/src/main/java/com/swyp/picke/domain/perspective/repository/CommentLikeRepository.java index 5d866fb4..0ea49a04 100644 --- a/src/main/java/com/swyp/picke/domain/perspective/repository/CommentLikeRepository.java +++ b/src/main/java/com/swyp/picke/domain/perspective/repository/CommentLikeRepository.java @@ -4,6 +4,7 @@ import com.swyp.picke.domain.perspective.entity.PerspectiveComment; import org.springframework.data.jpa.repository.JpaRepository; +import java.util.List; import java.util.Optional; public interface CommentLikeRepository extends JpaRepository { @@ -11,4 +12,8 @@ public interface CommentLikeRepository extends JpaRepository boolean existsByCommentAndUserId(PerspectiveComment comment, Long userId); Optional findByCommentAndUserId(PerspectiveComment comment, Long userId); + + void deleteAllByCommentIn(List comments); + + void deleteAllByComment(PerspectiveComment comment); } diff --git a/src/main/java/com/swyp/picke/domain/perspective/repository/CommentReportRepository.java b/src/main/java/com/swyp/picke/domain/perspective/repository/CommentReportRepository.java index 988183b6..a22592ad 100644 --- a/src/main/java/com/swyp/picke/domain/perspective/repository/CommentReportRepository.java +++ b/src/main/java/com/swyp/picke/domain/perspective/repository/CommentReportRepository.java @@ -4,9 +4,15 @@ import com.swyp.picke.domain.perspective.entity.PerspectiveComment; import org.springframework.data.jpa.repository.JpaRepository; +import java.util.List; + public interface CommentReportRepository extends JpaRepository { boolean existsByCommentAndUserId(PerspectiveComment comment, Long userId); long countByComment(PerspectiveComment comment); + + void deleteAllByCommentIn(List comments); + + void deleteAllByComment(PerspectiveComment comment); } diff --git a/src/main/java/com/swyp/picke/domain/perspective/repository/PerspectiveCommentRepository.java b/src/main/java/com/swyp/picke/domain/perspective/repository/PerspectiveCommentRepository.java index b65fd2ac..88b0c2cb 100644 --- a/src/main/java/com/swyp/picke/domain/perspective/repository/PerspectiveCommentRepository.java +++ b/src/main/java/com/swyp/picke/domain/perspective/repository/PerspectiveCommentRepository.java @@ -12,6 +12,8 @@ public interface PerspectiveCommentRepository extends JpaRepository { + List findByPerspective(Perspective perspective); + List findByPerspectiveOrderByCreatedAtDesc(Perspective perspective, Pageable pageable); List findByPerspectiveAndCreatedAtBeforeOrderByCreatedAtDesc(Perspective perspective, LocalDateTime cursor, Pageable pageable); diff --git a/src/main/java/com/swyp/picke/domain/perspective/repository/PerspectiveLikeRepository.java b/src/main/java/com/swyp/picke/domain/perspective/repository/PerspectiveLikeRepository.java index 4dd3b20b..0262f529 100644 --- a/src/main/java/com/swyp/picke/domain/perspective/repository/PerspectiveLikeRepository.java +++ b/src/main/java/com/swyp/picke/domain/perspective/repository/PerspectiveLikeRepository.java @@ -22,4 +22,6 @@ public interface PerspectiveLikeRepository extends JpaRepository findByUserIdOrderByCreatedAtDesc(@Param("userId") Long userId, Pageable pageable); long countByUserId(Long userId); + + void deleteAllByPerspective(Perspective perspective); } diff --git a/src/main/java/com/swyp/picke/domain/perspective/repository/PerspectiveReportRepository.java b/src/main/java/com/swyp/picke/domain/perspective/repository/PerspectiveReportRepository.java index 92692dbf..06f89064 100644 --- a/src/main/java/com/swyp/picke/domain/perspective/repository/PerspectiveReportRepository.java +++ b/src/main/java/com/swyp/picke/domain/perspective/repository/PerspectiveReportRepository.java @@ -9,4 +9,6 @@ public interface PerspectiveReportRepository extends JpaRepository comments = perspectiveCommentRepository.findByPerspective(perspective); + if (!comments.isEmpty()) { + commentLikeRepository.deleteAllByCommentIn(comments); + commentReportRepository.deleteAllByCommentIn(comments); + } perspectiveCommentRepository.deleteAllByPerspective(perspective); + + perspectiveLikeRepository.deleteAllByPerspective(perspective); + perspectiveReportRepository.deleteAllByPerspective(perspective); perspectiveRepository.delete(perspective); } diff --git a/src/main/java/com/swyp/picke/domain/user/repository/UserSettingsRepository.java b/src/main/java/com/swyp/picke/domain/user/repository/UserSettingsRepository.java index 13cea585..51f61063 100644 --- a/src/main/java/com/swyp/picke/domain/user/repository/UserSettingsRepository.java +++ b/src/main/java/com/swyp/picke/domain/user/repository/UserSettingsRepository.java @@ -1,10 +1,18 @@ package com.swyp.picke.domain.user.repository; import com.swyp.picke.domain.user.entity.UserSettings; +import java.util.List; import java.util.Optional; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; public interface UserSettingsRepository extends JpaRepository { Optional findByUserId(Long userId); + + @Query("SELECT s.user.id FROM UserSettings s WHERE s.newBattleEnabled = true") + List findUserIdsByNewBattleEnabledTrue(); + + @Query("SELECT s.user.id FROM UserSettings s WHERE s.marketingEventEnabled = true") + List findUserIdsByMarketingEventEnabledTrue(); } From d0416313c9413640489a1c89d4f646082ff0a14f Mon Sep 17 00:00:00 2001 From: Youwol <153346797+si-zero@users.noreply.github.com> Date: Tue, 16 Jun 2026 10:30:09 +0900 Subject: [PATCH 10/29] =?UTF-8?q?[Chore]=20adMob=20=ED=81=AC=EB=A1=A4?= =?UTF-8?q?=EB=A7=81=20=ED=8C=8C=EC=9D=BC=20=EC=84=A4=EC=A0=95:=20adMob=20?= =?UTF-8?q?=ED=81=AC=EB=A1=A4=EB=A7=81=20=ED=8C=8C=EC=9D=BC=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95=20#269?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## #️⃣ 연관된 이슈 - closed #268 ## 📝 작업 내용 ### 🔨 Chore | 내용 | 파일 | |------|------| | 크롤링 파일 추가 | `app-ads.txt` | | | | ## 📌 공유 사항 > 없음 ## ✅ 체크리스트 - [x] Reviewer에 팀원들을 선택했나요? - [x] Assignees에 본인을 선택했나요? - [x] 컨벤션에 맞는 Type을 선택했나요? - [x] Development에 이슈를 연동했나요? - [x] Merge 하려는 브랜치가 올바르게 설정되어 있나요? - [x] 컨벤션을 지키고 있나요? - [x] 로컬에서 실행했을 때 에러가 발생하지 않나요? - [ ] 팀원들에게 PR 링크 공유를 했나요? ## 📸 스크린샷 > 없음 ## 💬 리뷰 요구사항 > 없음 --- src/main/resources/static/app-ads.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 src/main/resources/static/app-ads.txt diff --git a/src/main/resources/static/app-ads.txt b/src/main/resources/static/app-ads.txt new file mode 100644 index 00000000..34ac9e6f --- /dev/null +++ b/src/main/resources/static/app-ads.txt @@ -0,0 +1 @@ +google.com, pub-1028210519429318, DIRECT, f08c47fec0942fa0 \ No newline at end of file From ec258822a4dc7be0d6bea208372a81756d03eaa7 Mon Sep 17 00:00:00 2001 From: Youwol <153346797+si-zero@users.noreply.github.com> Date: Tue, 16 Jun 2026 11:02:12 +0900 Subject: [PATCH 11/29] =?UTF-8?q?#270=20[Feat]=20=EC=84=A4=EC=A0=95=20?= =?UTF-8?q?=ED=8C=8C=EC=9D=BC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## #️⃣ 연관된 이슈 - #268 ## 📝 작업 내용 ### ✨ Feat | 내용 | 파일 | |------|------| | 허용 설정 추가 | `SecurityConfig.java` | | | | ## 📌 공유 사항 > 없음 ## ✅ 체크리스트 - [x] Reviewer에 팀원들을 선택했나요? - [x] Assignees에 본인을 선택했나요? - [x] 컨벤션에 맞는 Type을 선택했나요? - [x] Development에 이슈를 연동했나요? - [x] Merge 하려는 브랜치가 올바르게 설정되어 있나요? - [x] 컨벤션을 지키고 있나요? - [x] 로컬에서 실행했을 때 에러가 발생하지 않나요? - [ ] 팀원들에게 PR 링크 공유를 했나요? ## 📸 스크린샷 > 없음 ## 💬 리뷰 요구사항 > 없음 --- src/main/java/com/swyp/picke/global/config/SecurityConfig.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/swyp/picke/global/config/SecurityConfig.java b/src/main/java/com/swyp/picke/global/config/SecurityConfig.java index 614589ea..bf407fc6 100644 --- a/src/main/java/com/swyp/picke/global/config/SecurityConfig.java +++ b/src/main/java/com/swyp/picke/global/config/SecurityConfig.java @@ -49,7 +49,8 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { "/api/v1/admob/reward/**", "/report/**", "/battle/**", - "/.well-known/**" + "/.well-known/**", + "/app-ads.txt" ).permitAll() // 2. 관리자 HTML 화면 렌더링 요청 From 4c45999b672b4c7dbf498144cecb43747e6e6b4b Mon Sep 17 00:00:00 2001 From: Youwol <153346797+si-zero@users.noreply.github.com> Date: Tue, 16 Jun 2026 11:13:34 +0900 Subject: [PATCH 12/29] =?UTF-8?q?[Chore]=20JWT=ED=95=84=ED=84=B0=20?= =?UTF-8?q?=EC=84=A4=EC=A0=95=20#271?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../picke/domain/oauth/jwt/JwtFilter.java | 60 +++++++++---------- 1 file changed, 28 insertions(+), 32 deletions(-) diff --git a/src/main/java/com/swyp/picke/domain/oauth/jwt/JwtFilter.java b/src/main/java/com/swyp/picke/domain/oauth/jwt/JwtFilter.java index 8637f470..a1c51b41 100644 --- a/src/main/java/com/swyp/picke/domain/oauth/jwt/JwtFilter.java +++ b/src/main/java/com/swyp/picke/domain/oauth/jwt/JwtFilter.java @@ -25,54 +25,54 @@ public class JwtFilter extends OncePerRequestFilter { private final JwtProvider jwtProvider; private final ObjectMapper objectMapper = new ObjectMapper(); - // 1. 스웨거 및 인증 관련 경로를 더 넓게 잡았습니다. + // 1. 화이트리스트 상수 관리 private static final List WHITELIST = List.of( "/api/v1/admob/reward", - "/swagger-ui", - "/v3/api-docs", "/api/v1/admin/login", "/api/v1/admin/picke", "/js", "/css", "/images", "/favicon.ico", - "/api/v1/auth", // 로그인, 리프레시 등 인증 관련 전체 - "/swagger-ui", // 스웨거 UI 리소스 전체 - "/v3/api-docs", // OpenAPI 스펙 전체 - "/api/v1/home", // 홈 화면 - "/api/v1/notices", // 공지사항 - "/api/test", // 테스트용 - "/result", // 공유 링크 리다이렉트 - "/report", // 철학자 리포트 딥링크 - "/battle", // 배틀 딥링크 - "/api/v1/share/recap/", // 공개 리캡 공유 조회 - "/.well-known", // Android App Links 인증 - "/api/v1/resources" // 이미지, 오디오 파일 (Presigned URL) + "/api/v1/auth", + "/swagger-ui", + "/v3/api-docs", + "/api/v1/home", + "/api/v1/notices", + "/api/test", + "/result", + "/report", + "/battle", + "/api/v1/share/recap/", + "/.well-known", + "/api/v1/resources", + "/app-ads.txt" ); + @Override + protected boolean shouldNotFilter(HttpServletRequest request) throws ServletException { + String requestUri = request.getRequestURI(); + return isWhitelisted(requestUri); + } + @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { String requestUri = request.getRequestURI(); - boolean isWhitelist = isWhitelisted(requestUri); - - log.info("[JwtFilter Debug] URI: {}, isWhitelisted: {}", requestUri, isWhitelist); + log.info("[JwtFilter Debug] Processing URI: {}", requestUri); try { - // 1. 화이트리스트 검사 전, 무조건 토큰부터 꺼냅니다. String token = resolveToken(request); if (token != null) { - // 2. 토큰이 존재하면 유효성을 검사합니다. if (!jwtProvider.validateToken(token)) { log.error("[JwtFilter] Invalid or Expired token for URI: {}", requestUri); setErrorResponse(response, ErrorCode.AUTH_ACCESS_TOKEN_EXPIRED); return; } - // 3. 토큰이 유효하다면 SecurityContext에 유저 정보(userId)를 저장합니다. Long userId = jwtProvider.getUserId(token); String role = jwtProvider.getRole(token); String authorityName = (role != null && role.startsWith("ROLE_")) ? role : "ROLE_" + role; @@ -87,15 +87,12 @@ protected void doFilterInternal(HttpServletRequest request, SecurityContextHolder.getContext().setAuthentication(authentication); } else { - // 4. 토큰이 비어있을 때, 화이트리스트(홈 화면 등)가 아니라면 에러를 던집니다. - if (!isWhitelist) { - log.warn("[JwtFilter] Token missing for URI: {}", requestUri); - setErrorResponse(response, ErrorCode.AUTH_UNAUTHORIZED); - return; - } + // shouldNotFilter가 잡지 못한 주소 중 토큰이 없다면 무조건 401 차단 + log.warn("[JwtFilter] Token missing for secured URI: {}", requestUri); + setErrorResponse(response, ErrorCode.AUTH_UNAUTHORIZED); + return; } - // 5. [토큰 검증을 무사히 마쳤거나] or [토큰이 없는 비회원인데 화이트리스트인 경우] 다음 필터로 넘어갑니다. filterChain.doFilter(request, response); } catch (Exception e) { @@ -112,7 +109,7 @@ private void setErrorResponse(HttpServletResponse response, ErrorCode errorCode) errorCode.getHttpStatus().value(), errorCode.getCode(), errorCode.getMessage() - ); + ); String result = objectMapper.writeValueAsString(errorResponse); response.getWriter().write(result); @@ -127,7 +124,6 @@ private String resolveToken(HttpServletRequest request) { } private boolean isWhitelisted(String uri) { - // 1. URI가 화이트리스트의 어떤 값으로든 시작하면 true - return WHITELIST.stream().anyMatch(uri::startsWith); + return WHITELIST.stream().anyMatch(white -> uri.equals(white) || uri.startsWith(white)); } -} +} \ No newline at end of file From e0c9c1cea8f11e01f75757060b94ac71aacb5524 Mon Sep 17 00:00:00 2001 From: Youwol <153346797+si-zero@users.noreply.github.com> Date: Thu, 18 Jun 2026 23:28:00 +0900 Subject: [PATCH 13/29] =?UTF-8?q?#275=20[Fix]=20AdMob=20SSV=20=EC=BD=9C?= =?UTF-8?q?=EB=B0=B1=20=ED=8C=8C=EB=9D=BC=EB=AF=B8=ED=84=B0=20optional=20?= =?UTF-8?q?=EC=B2=98=EB=A6=AC=20=EB=B0=8F=20=EC=84=9C=EB=AA=85=20=EA=B2=80?= =?UTF-8?q?=EC=A6=9D=20=ED=99=9C=EC=84=B1=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .tool-versions | 1 + gradlew | 0 .../domain/oauth/client/AppleOAuthClient.java | 2 -- .../controller/AdMobRewardController.java | 9 ++++--- .../dto/request/AdMobRewardRequest.java | 14 +++++----- .../service/AdMobRewardServiceImpl.java | 26 ++++++++++++------- .../swyp/picke/global/config/AdMobConfig.java | 15 +++++++++++ src/main/resources/application.yml | 4 ++- .../service/AdMobRewardServiceTest.java | 24 ++++++++++++++++- 9 files changed, 72 insertions(+), 23 deletions(-) create mode 100644 .tool-versions mode change 100644 => 100755 gradlew diff --git a/.tool-versions b/.tool-versions new file mode 100644 index 00000000..e8fc3f8e --- /dev/null +++ b/.tool-versions @@ -0,0 +1 @@ +nodejs 20.18.1 diff --git a/gradlew b/gradlew old mode 100644 new mode 100755 diff --git a/src/main/java/com/swyp/picke/domain/oauth/client/AppleOAuthClient.java b/src/main/java/com/swyp/picke/domain/oauth/client/AppleOAuthClient.java index 2d1c3c88..97b3cda4 100644 --- a/src/main/java/com/swyp/picke/domain/oauth/client/AppleOAuthClient.java +++ b/src/main/java/com/swyp/picke/domain/oauth/client/AppleOAuthClient.java @@ -193,6 +193,4 @@ private PrivateKey getPrivateKey() { throw new RuntimeException("애플 비밀키 생성 실패"); } } - - } \ No newline at end of file diff --git a/src/main/java/com/swyp/picke/domain/reward/controller/AdMobRewardController.java b/src/main/java/com/swyp/picke/domain/reward/controller/AdMobRewardController.java index 88bb50e0..172579d5 100644 --- a/src/main/java/com/swyp/picke/domain/reward/controller/AdMobRewardController.java +++ b/src/main/java/com/swyp/picke/domain/reward/controller/AdMobRewardController.java @@ -31,10 +31,13 @@ public ApiResponse handleAdMobReward( AdMobRewardRequest request) { log.info("AdMob SSV 콜백 수신: transaction_id={}", request.transaction_id()); - // 서비스에서 "OK" 또는 "Already Processed" 수신 - String status = rewardService.processReward(request); + // AdMob 콘솔 URL 검증 요청 (파라미터 없는 빈 요청) 시 200 반환 + if (request.transaction_id() == null || request.signature() == null) { + log.info("AdMob URL 검증 요청 수신 (파라미터 없음) - 200 반환"); + return ApiResponse.onSuccess(AdMobRewardResponse.from("OK")); + } - // DTO로 감싸서 반환 (명세서의 data { "reward_status": "..." } 구조 완성) + String status = rewardService.processReward(request); return ApiResponse.onSuccess(AdMobRewardResponse.from(status)); } } diff --git a/src/main/java/com/swyp/picke/domain/reward/dto/request/AdMobRewardRequest.java b/src/main/java/com/swyp/picke/domain/reward/dto/request/AdMobRewardRequest.java index af4b8716..7de12be0 100644 --- a/src/main/java/com/swyp/picke/domain/reward/dto/request/AdMobRewardRequest.java +++ b/src/main/java/com/swyp/picke/domain/reward/dto/request/AdMobRewardRequest.java @@ -23,14 +23,14 @@ public record AdMobRewardRequest( ) { public AdMobRewardRequest( @RequestParam(value = "ad_network", required = false) String ad_network, - @RequestParam("ad_unit") String ad_unit, + @RequestParam(value = "ad_unit", required = false) String ad_unit, @RequestParam(value = "custom_data", required = false) String custom_data, - @RequestParam("reward_amount") int reward_amount, - @RequestParam("reward_item") String reward_item, - @RequestParam("timestamp") long timestamp, - @RequestParam("transaction_id") String transaction_id, - @RequestParam("signature") String signature, - @RequestParam("key_id") String key_id, + @RequestParam(value = "reward_amount", required = false, defaultValue = "0") int reward_amount, + @RequestParam(value = "reward_item", required = false) String reward_item, + @RequestParam(value = "timestamp", required = false, defaultValue = "0") long timestamp, + @RequestParam(value = "transaction_id", required = false) String transaction_id, + @RequestParam(value = "signature", required = false) String signature, + @RequestParam(value = "key_id", required = false) String key_id, @RequestParam(value = "user_id", required = false) String user_id ) { this.ad_network = ad_network; diff --git a/src/main/java/com/swyp/picke/domain/reward/service/AdMobRewardServiceImpl.java b/src/main/java/com/swyp/picke/domain/reward/service/AdMobRewardServiceImpl.java index b77bb946..a56bb854 100644 --- a/src/main/java/com/swyp/picke/domain/reward/service/AdMobRewardServiceImpl.java +++ b/src/main/java/com/swyp/picke/domain/reward/service/AdMobRewardServiceImpl.java @@ -7,9 +7,10 @@ import com.swyp.picke.domain.user.entity.User; import com.swyp.picke.domain.user.enums.CreditType; import com.swyp.picke.domain.user.service.CreditService; -import com.swyp.picke.domain.user.service.UserService; // // 1. UserService 임포트 +import com.swyp.picke.domain.user.service.UserService; import com.swyp.picke.global.common.exception.CustomException; import com.swyp.picke.global.common.exception.ErrorCode; +import com.swyp.picke.global.config.AdMobConfig; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; @@ -24,8 +25,9 @@ public class AdMobRewardServiceImpl implements AdMobRewardService { private final RewardedAdsVerifier rewardedAdsVerifier; private final AdRewardHistoryRepository adRewardHistoryRepository; - private final UserService userService; // // 2. UserRepository 대신 UserService 사용 (태그 조회 로직 집중) + private final UserService userService; private final CreditService creditService; + private final AdMobConfig adMobConfig; @Override @Transactional @@ -33,24 +35,30 @@ public String processReward(AdMobRewardRequest request) { log.info("[AdMob] SSV 처리 시작: transaction_id={}, userTag={}, reward_amount={}, ad_unit={}", request.transaction_id(), request.getUserTag(), request.reward_amount(), request.ad_unit()); - // 1. 서명 검증 (공식 파라미터 기반) - /*if (!verifyAdMobSignature(request)) { + // 1. ad_unit 유효성 검사 + if (!adMobConfig.getAllowedUnitIds().contains(request.ad_unit())) { + log.warn("[AdMob] 허용되지 않은 ad_unit: {}", request.ad_unit()); + throw new CustomException(ErrorCode.REWARD_INVALID_SIGNATURE); + } + + // 2. 서명 검증 (공식 파라미터 기반) + if (!verifyAdMobSignature(request)) { log.warn("[AdMob] 서명 검증 실패: transaction_id={}", request.transaction_id()); throw new CustomException(ErrorCode.REWARD_INVALID_SIGNATURE); - }*/ + } - // 2. 중복 처리 방지 + // 3. 중복 처리 방지 if (adRewardHistoryRepository.existsByTransactionId(request.transaction_id())) { log.info("[AdMob] 이미 처리된 요청: transaction_id={}", request.transaction_id()); return "Already Processed"; } - // 3. 유저 확인 (custom_data → user_id 순으로 조회) + // 4. 유저 확인 (custom_data → user_id 순으로 조회) log.info("[AdMob] 유저 조회 시도: userTag={}", request.getUserTag()); User user = userService.findByUserTag(request.getUserTag()); log.info("[AdMob] 유저 확인 완료: userId={}", user.getId()); - // 4. 보상 이력 저장 후 즉시 id 확보 (saveAndFlush) + // 5. 보상 이력 저장 후 즉시 id 확보 (saveAndFlush) AdRewardHistory history = AdRewardHistory.builder() .transactionId(request.transaction_id()) .user(user) @@ -60,7 +68,7 @@ public String processReward(AdMobRewardRequest request) { adRewardHistoryRepository.saveAndFlush(history); log.info("[AdMob] 보상 이력 저장 완료: historyId={}", history.getId()); - // 5. 크레딧 적립 (history.getId()를 referenceId로 사용해 unique 충돌 방지) + // 6. 크레딧 적립 (history.getId()를 referenceId로 사용해 unique 충돌 방지) creditService.addCredit(user.getId(), CreditType.FREE_CHARGE, request.reward_amount(), history.getId()); log.info("[AdMob] 포인트 적립 완료: userId={}, amount={}, historyId={}", user.getId(), request.reward_amount(), history.getId()); diff --git a/src/main/java/com/swyp/picke/global/config/AdMobConfig.java b/src/main/java/com/swyp/picke/global/config/AdMobConfig.java index 59f0d842..cbcb2225 100644 --- a/src/main/java/com/swyp/picke/global/config/AdMobConfig.java +++ b/src/main/java/com/swyp/picke/global/config/AdMobConfig.java @@ -1,12 +1,27 @@ package com.swyp.picke.global.config; import com.google.crypto.tink.apps.rewardedads.RewardedAdsVerifier; +import lombok.Getter; +import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import java.util.List; + +@Getter @Configuration public class AdMobConfig { + @Value("${admob.reward.unit-id.ios}") + private String iosRewardUnitId; + + @Value("${admob.reward.unit-id.android}") + private String androidRewardUnitId; + + public List getAllowedUnitIds() { + return List.of(iosRewardUnitId, androidRewardUnitId); + } + @Bean public RewardedAdsVerifier rewardedAdsVerifier() { try { diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 447d5f29..e2671442 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -76,7 +76,9 @@ oauth: admob: app-id: ${ADMOB_APP_ID} reward: - unit-id: ${ADMOB_REWARD_UNIT_ID} + unit-id: + ios: ${ADMOB_REWARD_UNIT_ID_IOS} + android: ${ADMOB_REWARD_UNIT_ID_ANDROID} openai: api-key: ${OPENAI_API_KEY} diff --git a/src/test/java/com/swyp/picke/domain/reward/service/AdMobRewardServiceTest.java b/src/test/java/com/swyp/picke/domain/reward/service/AdMobRewardServiceTest.java index b0d7faa3..016a5024 100644 --- a/src/test/java/com/swyp/picke/domain/reward/service/AdMobRewardServiceTest.java +++ b/src/test/java/com/swyp/picke/domain/reward/service/AdMobRewardServiceTest.java @@ -18,6 +18,7 @@ import com.swyp.picke.domain.user.enums.UserStatus; import com.swyp.picke.domain.user.service.CreditService; import com.swyp.picke.domain.user.service.UserService; +import com.swyp.picke.global.config.AdMobConfig; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -26,6 +27,11 @@ import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.test.util.ReflectionTestUtils; +import java.util.List; + +import static org.mockito.BDDMockito.willDoNothing; +import static org.mockito.Mockito.doAnswer; + @ExtendWith(MockitoExtension.class) class AdMobRewardServiceTest { @@ -44,6 +50,9 @@ class AdMobRewardServiceTest { @Mock private CreditService creditService; + @Mock + private AdMobConfig adMobConfig; + @Test @DisplayName("// 1. 정상적인 광고 시청 시 보상 이력이 저장되고 크레딧이 적립된다.") void processReward_Success() throws Exception { @@ -58,6 +67,19 @@ void processReward_Success() throws Exception { .build(); ReflectionTestUtils.setField(mockUser, "id", 1L); + // ad_unit 허용 목록 Mock + given(adMobConfig.getAllowedUnitIds()).willReturn(List.of("ca-app-pub-3940256099942544/5224354917")); + + // 서명 검증 Mock (검증 통과) + willDoNothing().given(rewardedAdsVerifier).verify(org.mockito.ArgumentMatchers.anyString()); + + // saveAndFlush 시 ID 세팅 Mock + doAnswer(invocation -> { + AdRewardHistory history = invocation.getArgument(0); + ReflectionTestUtils.setField(history, "id", 1L); + return history; + }).when(adRewardHistoryRepository).saveAndFlush(any(AdRewardHistory.class)); + // // 1. 중복 체크 Mock given(adRewardHistoryRepository.existsByTransactionId(request.transaction_id())).willReturn(false); @@ -76,7 +98,7 @@ void processReward_Success() throws Exception { // // 4. 호출 검증 verify(creditService, times(1)).addCredit(eq(1L), eq(CreditType.FREE_CHARGE), eq(100), anyLong()); - verify(adRewardHistoryRepository, times(1)).save(any(AdRewardHistory.class)); + verify(adRewardHistoryRepository, times(1)).saveAndFlush(any(AdRewardHistory.class)); verify(userService, times(1)).findByUserTag("pique-1cc4a030"); } From ab2cb787dbaa98c6877ce6c2c662bac0d60b134b Mon Sep 17 00:00:00 2001 From: Youwol <153346797+si-zero@users.noreply.github.com> Date: Fri, 19 Jun 2026 01:36:26 +0900 Subject: [PATCH 14/29] =?UTF-8?q?#277=20[Fix]=20AdMob=20SSV=20=EC=BD=9C?= =?UTF-8?q?=EB=B0=B1=20URL=20=EA=B2=80=EC=A6=9D=20=EC=9A=94=EC=B2=AD=20?= =?UTF-8?q?=EC=B2=98=EB=A6=AC=20=EC=8B=A4=ED=8C=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/reward/controller/AdMobRewardController.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/swyp/picke/domain/reward/controller/AdMobRewardController.java b/src/main/java/com/swyp/picke/domain/reward/controller/AdMobRewardController.java index 172579d5..5eba1942 100644 --- a/src/main/java/com/swyp/picke/domain/reward/controller/AdMobRewardController.java +++ b/src/main/java/com/swyp/picke/domain/reward/controller/AdMobRewardController.java @@ -31,9 +31,9 @@ public ApiResponse handleAdMobReward( AdMobRewardRequest request) { log.info("AdMob SSV 콜백 수신: transaction_id={}", request.transaction_id()); - // AdMob 콘솔 URL 검증 요청 (파라미터 없는 빈 요청) 시 200 반환 - if (request.transaction_id() == null || request.signature() == null) { - log.info("AdMob URL 검증 요청 수신 (파라미터 없음) - 200 반환"); + // 실제 SSV 콜백에는 key_id가 반드시 포함됨 — key_id 없으면 AdMob 콘솔 URL 검증 요청으로 판별 + if (request.transaction_id() == null || request.signature() == null || request.key_id() == null) { + log.info("AdMob URL 검증 요청 수신 - 200 반환"); return ApiResponse.onSuccess(AdMobRewardResponse.from("OK")); } From 04d947c7147cd1643699f93502fdd4b70723cd2b Mon Sep 17 00:00:00 2001 From: Youwol <153346797+si-zero@users.noreply.github.com> Date: Fri, 19 Jun 2026 01:50:06 +0900 Subject: [PATCH 15/29] =?UTF-8?q?#279=20[Fix]=20AdMob=20SSV=20=EC=97=94?= =?UTF-8?q?=EB=93=9C=ED=8F=AC=EC=9D=B8=ED=8A=B8=20=EA=B2=80=EC=A6=9D=20?= =?UTF-8?q?=EC=8B=A4=ED=8C=A8=20=EC=8B=9C=20=ED=95=AD=EC=83=81=20200=20?= =?UTF-8?q?=EB=B0=98=ED=99=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../reward/controller/AdMobRewardController.java | 11 ++++++++--- .../domain/reward/service/AdMobRewardServiceImpl.java | 4 ++-- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/swyp/picke/domain/reward/controller/AdMobRewardController.java b/src/main/java/com/swyp/picke/domain/reward/controller/AdMobRewardController.java index 5eba1942..821eeddf 100644 --- a/src/main/java/com/swyp/picke/domain/reward/controller/AdMobRewardController.java +++ b/src/main/java/com/swyp/picke/domain/reward/controller/AdMobRewardController.java @@ -31,13 +31,18 @@ public ApiResponse handleAdMobReward( AdMobRewardRequest request) { log.info("AdMob SSV 콜백 수신: transaction_id={}", request.transaction_id()); - // 실제 SSV 콜백에는 key_id가 반드시 포함됨 — key_id 없으면 AdMob 콘솔 URL 검증 요청으로 판별 + // AdMob SSV 스펙: 검증 실패 포함 모든 경우에 200 반환 (비정상 응답 시 구글이 재시도) if (request.transaction_id() == null || request.signature() == null || request.key_id() == null) { log.info("AdMob URL 검증 요청 수신 - 200 반환"); return ApiResponse.onSuccess(AdMobRewardResponse.from("OK")); } - String status = rewardService.processReward(request); - return ApiResponse.onSuccess(AdMobRewardResponse.from(status)); + try { + String status = rewardService.processReward(request); + return ApiResponse.onSuccess(AdMobRewardResponse.from(status)); + } catch (Exception e) { + log.warn("[AdMob] 처리 실패 - 보상 미지급 후 200 반환: transaction_id={}, reason={}", request.transaction_id(), e.getMessage()); + return ApiResponse.onSuccess(AdMobRewardResponse.from("OK")); + } } } diff --git a/src/main/java/com/swyp/picke/domain/reward/service/AdMobRewardServiceImpl.java b/src/main/java/com/swyp/picke/domain/reward/service/AdMobRewardServiceImpl.java index a56bb854..bbb0f93d 100644 --- a/src/main/java/com/swyp/picke/domain/reward/service/AdMobRewardServiceImpl.java +++ b/src/main/java/com/swyp/picke/domain/reward/service/AdMobRewardServiceImpl.java @@ -38,13 +38,13 @@ public String processReward(AdMobRewardRequest request) { // 1. ad_unit 유효성 검사 if (!adMobConfig.getAllowedUnitIds().contains(request.ad_unit())) { log.warn("[AdMob] 허용되지 않은 ad_unit: {}", request.ad_unit()); - throw new CustomException(ErrorCode.REWARD_INVALID_SIGNATURE); + return "OK"; } // 2. 서명 검증 (공식 파라미터 기반) if (!verifyAdMobSignature(request)) { log.warn("[AdMob] 서명 검증 실패: transaction_id={}", request.transaction_id()); - throw new CustomException(ErrorCode.REWARD_INVALID_SIGNATURE); + return "OK"; } // 3. 중복 처리 방지 From d9ea3b552b3f82a6c3bebdad34f3e4ff30d4cd03 Mon Sep 17 00:00:00 2001 From: Youwol <153346797+si-zero@users.noreply.github.com> Date: Fri, 19 Jun 2026 15:59:05 +0900 Subject: [PATCH 16/29] =?UTF-8?q?#283=20[Fix]=20/me/content-activities=20v?= =?UTF-8?q?oteSide=20null=20=EB=B0=98=ED=99=98=20=EB=B2=84=EA=B7=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...0619_01__backfill_battle_option_display_order.sql | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 src/main/resources/db/migration/V20260619_01__backfill_battle_option_display_order.sql diff --git a/src/main/resources/db/migration/V20260619_01__backfill_battle_option_display_order.sql b/src/main/resources/db/migration/V20260619_01__backfill_battle_option_display_order.sql new file mode 100644 index 00000000..641b3e1b --- /dev/null +++ b/src/main/resources/db/migration/V20260619_01__backfill_battle_option_display_order.sql @@ -0,0 +1,12 @@ +-- display_order가 NULL인 battle_options 백필: 같은 battle_id 내 id 오름차순으로 1, 2 배정 +UPDATE battle_options bo +SET display_order = sub.row_num +FROM ( + SELECT id, + ROW_NUMBER() OVER (PARTITION BY battle_id ORDER BY id) AS row_num + FROM battle_options + WHERE display_order IS NULL +) sub +WHERE bo.id = sub.id; + +ALTER TABLE battle_options ALTER COLUMN display_order SET NOT NULL; From ec27b01f1fbe39e8ef23810838fe71a933eae5d0 Mon Sep 17 00:00:00 2001 From: Youwol <153346797+si-zero@users.noreply.github.com> Date: Sat, 20 Jun 2026 23:13:27 +0900 Subject: [PATCH 17/29] =?UTF-8?q?#285=20[Feat]=20content-activities=20?= =?UTF-8?q?=EC=9D=91=EB=8B=B5=EC=97=90=20option=5Ftitle=20=ED=95=84?= =?UTF-8?q?=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/api-specs/user-api.md | 3 ++- .../domain/user/dto/response/ContentActivityListResponse.java | 1 + .../java/com/swyp/picke/domain/user/service/MypageService.java | 2 ++ 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/api-specs/user-api.md b/docs/api-specs/user-api.md index 917fa619..78594f02 100644 --- a/docs/api-specs/user-api.md +++ b/docs/api-specs/user-api.md @@ -227,7 +227,8 @@ "nickname": "사색하는고양이", "character_type": "CAT" }, - "stance": "반대", + "vote_side": "CON", + "option_title": "반대합니다", "content": "제도가 무서운 건, 사회적 압력이 선택을 의무로 바꿀 수 있다는 거예요.", "like_count": 1340, "created_at": "2026-03-08T12:00:00" diff --git a/src/main/java/com/swyp/picke/domain/user/dto/response/ContentActivityListResponse.java b/src/main/java/com/swyp/picke/domain/user/dto/response/ContentActivityListResponse.java index ffc0eba9..f99aa885 100644 --- a/src/main/java/com/swyp/picke/domain/user/dto/response/ContentActivityListResponse.java +++ b/src/main/java/com/swyp/picke/domain/user/dto/response/ContentActivityListResponse.java @@ -21,6 +21,7 @@ public record ContentActivityItem( String battleTitle, AuthorInfo author, VoteSide voteSide, + String optionTitle, String content, int likeCount, LocalDateTime createdAt diff --git a/src/main/java/com/swyp/picke/domain/user/service/MypageService.java b/src/main/java/com/swyp/picke/domain/user/service/MypageService.java index b9a7724c..9f6d2302 100644 --- a/src/main/java/com/swyp/picke/domain/user/service/MypageService.java +++ b/src/main/java/com/swyp/picke/domain/user/service/MypageService.java @@ -252,6 +252,7 @@ private ContentActivityListResponse.ContentActivityItem toActivityItem( ); VoteSide voteSide = BattleOptionDisplay.voteSide(option); + String optionTitle = BattleOptionDisplay.opinion(option); return new ContentActivityListResponse.ContentActivityItem( activityId, activityType, @@ -260,6 +261,7 @@ private ContentActivityListResponse.ContentActivityItem toActivityItem( battle != null ? battle.getTitle() : null, authorInfo, voteSide, + optionTitle, content, perspective.getLikeCount(), createdAt From 6663e7a5d4054db6dd3af80694e09ebfcacfe23a Mon Sep 17 00:00:00 2001 From: Youwol <153346797+si-zero@users.noreply.github.com> Date: Wed, 24 Jun 2026 14:12:57 +0900 Subject: [PATCH 18/29] =?UTF-8?q?#287=20[Fix]=20AdMob=20SSV=20=EC=84=9C?= =?UTF-8?q?=EB=AA=85=20=EA=B2=80=EC=A6=9D=20=EC=98=A4=EB=A5=98=EB=A1=9C=20?= =?UTF-8?q?=EC=9D=B8=ED=95=9C=20=ED=8F=AC=EC=9D=B8=ED=8A=B8=20=EB=AF=B8?= =?UTF-8?q?=EC=A7=80=EA=B8=89=20=EB=B2=84=EA=B7=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../reward/service/AdMobRewardServiceImpl.java | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/swyp/picke/domain/reward/service/AdMobRewardServiceImpl.java b/src/main/java/com/swyp/picke/domain/reward/service/AdMobRewardServiceImpl.java index bbb0f93d..ce1ebd63 100644 --- a/src/main/java/com/swyp/picke/domain/reward/service/AdMobRewardServiceImpl.java +++ b/src/main/java/com/swyp/picke/domain/reward/service/AdMobRewardServiceImpl.java @@ -82,9 +82,9 @@ public String processReward(AdMobRewardRequest request) { */ private boolean verifyAdMobSignature(AdMobRewardRequest request) { try { - // // 조립 시 signature와 key_id는 제외하고 나머지 8개 파라미터를 조립합니다. - // // 순서: ad_network -> ad_unit -> custom_data -> reward_amount -> reward_item -> timestamp -> transaction_id -> user_id - StringBuilder sb = new StringBuilder(); + // RewardedAdsVerifier.verify()는 내부에서 URI.getQuery()를 사용하므로 scheme을 포함한 완전한 URL이어야 함 + // key_id와 signature는 반드시 마지막 두 파라미터 순서로 위치해야 함 (Tink 라이브러리 스펙) + StringBuilder sb = new StringBuilder("https://admob.google.com/reward?"); if (request.ad_network() != null) sb.append("ad_network=").append(request.ad_network()).append("&"); sb.append("ad_unit=").append(request.ad_unit()).append("&"); if (request.custom_data() != null) sb.append("custom_data=").append(request.custom_data()).append("&"); @@ -93,11 +93,12 @@ private boolean verifyAdMobSignature(AdMobRewardRequest request) { sb.append("timestamp=").append(request.timestamp()).append("&"); sb.append("transaction_id=").append(request.transaction_id()); if (request.user_id() != null) sb.append("&user_id=").append(request.user_id()); + sb.append("&key_id=").append(request.key_id()); + sb.append("&signature=").append(request.signature()); - String fullQueryString = sb.toString(); + String fullUrl = sb.toString(); - // // Tink 라이브러리를 통해 signature와 key_id를 사용하여 검증 - rewardedAdsVerifier.verify(fullQueryString); + rewardedAdsVerifier.verify(fullUrl); return true; } catch (GeneralSecurityException e) { log.error("보상 서명 보안 에러: {}", e.getMessage()); From 39aca844fe6442521a8dad6631082248a388c2f5 Mon Sep 17 00:00:00 2001 From: Youwol <153346797+si-zero@users.noreply.github.com> Date: Sun, 5 Jul 2026 21:35:10 +0900 Subject: [PATCH 19/29] =?UTF-8?q?#289=20[Fix]=20=EC=98=A4=EB=8A=98?= =?UTF-8?q?=EC=9D=98=20=EB=B0=B0=ED=8B=80=20=EA=B0=9C=EC=88=98=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../swyp/picke/domain/battle/service/BattleServiceImpl.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/swyp/picke/domain/battle/service/BattleServiceImpl.java b/src/main/java/com/swyp/picke/domain/battle/service/BattleServiceImpl.java index 6c661817..4fb08eee 100644 --- a/src/main/java/com/swyp/picke/domain/battle/service/BattleServiceImpl.java +++ b/src/main/java/com/swyp/picke/domain/battle/service/BattleServiceImpl.java @@ -199,11 +199,11 @@ public BattleListResponse getBattles(int page, int size, String status) { @Transactional public TodayBattleListResponse getTodayBattles() { LocalDate today = LocalDate.now(); - ensureTodayPicks(today, 3); + ensureTodayPicks(today, 1); List battles = battleRepository.findByTargetDateAndStatusAndDeletedAtIsNull(today, BattleStatus.PUBLISHED); List limitedBattles = battles.stream() - .limit(3) + .limit(1) .collect(Collectors.toList()); List items = convertToTodayResponses(limitedBattles); From 11e2da13ce3302da247f5de8ab312f3e3c4c7d93 Mon Sep 17 00:00:00 2001 From: Youwol <153346797+si-zero@users.noreply.github.com> Date: Sun, 5 Jul 2026 22:27:08 +0900 Subject: [PATCH 20/29] =?UTF-8?q?#293=20[Fix]=20=EC=82=AC=EC=A0=84?= =?UTF-8?q?=ED=88=AC=ED=91=9C=20=EC=B2=A0=ED=95=99=EC=9E=90=20=EC=95=84?= =?UTF-8?q?=EC=9D=B4=EC=BD=98=20=EB=AF=B8=EB=85=B8=EC=B6=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/api-specs/home-api.md | 1 + docs/api-specs/poll-api.md | 1 + .../admin/dto/poll/request/AdminPollOptionRequest.java | 3 ++- .../home/dto/response/HomeTodayVoteOptionResponse.java | 3 ++- .../com/swyp/picke/domain/home/service/HomeService.java | 6 +++++- .../swyp/picke/domain/poll/converter/PollConverter.java | 9 ++++++++- .../domain/poll/dto/response/PollOptionResponse.java | 3 ++- .../com/swyp/picke/domain/poll/entity/PollOption.java | 9 +++++++-- .../swyp/picke/domain/poll/service/PollServiceImpl.java | 4 +++- .../V20260705_02__add_image_url_to_poll_options.sql | 3 +++ .../swyp/picke/domain/home/service/HomeServiceTest.java | 4 ++++ 11 files changed, 38 insertions(+), 8 deletions(-) create mode 100644 src/main/resources/db/migration/V20260705_02__add_image_url_to_poll_options.sql diff --git a/docs/api-specs/home-api.md b/docs/api-specs/home-api.md index 32efc238..9719ecdf 100644 --- a/docs/api-specs/home-api.md +++ b/docs/api-specs/home-api.md @@ -48,6 +48,7 @@ - `options[]` - `label` - `title` + - `imageUrl` (철학자 아이콘 이미지 URL, 미등록 시 `null`) --- diff --git a/docs/api-specs/poll-api.md b/docs/api-specs/poll-api.md index f6258f56..74b417cb 100644 --- a/docs/api-specs/poll-api.md +++ b/docs/api-specs/poll-api.md @@ -28,6 +28,7 @@ - `options[]` - `label` (`A`, `B`, ...) - `title` + - `imageUrl` (철학자 아이콘 이미지 경로) ### 2.2 Poll 목록 - `GET /api/v1/admin/polls` diff --git a/src/main/java/com/swyp/picke/domain/admin/dto/poll/request/AdminPollOptionRequest.java b/src/main/java/com/swyp/picke/domain/admin/dto/poll/request/AdminPollOptionRequest.java index 953df8f8..4a554b45 100644 --- a/src/main/java/com/swyp/picke/domain/admin/dto/poll/request/AdminPollOptionRequest.java +++ b/src/main/java/com/swyp/picke/domain/admin/dto/poll/request/AdminPollOptionRequest.java @@ -5,7 +5,8 @@ public record AdminPollOptionRequest( PollOptionLabel label, String title, - Integer displayOrder + Integer displayOrder, + String imageUrl ) {} diff --git a/src/main/java/com/swyp/picke/domain/home/dto/response/HomeTodayVoteOptionResponse.java b/src/main/java/com/swyp/picke/domain/home/dto/response/HomeTodayVoteOptionResponse.java index 510c59dc..b5ce1212 100644 --- a/src/main/java/com/swyp/picke/domain/home/dto/response/HomeTodayVoteOptionResponse.java +++ b/src/main/java/com/swyp/picke/domain/home/dto/response/HomeTodayVoteOptionResponse.java @@ -4,5 +4,6 @@ public record HomeTodayVoteOptionResponse( BattleOptionLabel label, - String title + String title, + String imageUrl ) {} diff --git a/src/main/java/com/swyp/picke/domain/home/service/HomeService.java b/src/main/java/com/swyp/picke/domain/home/service/HomeService.java index 8321586a..032dd5cd 100644 --- a/src/main/java/com/swyp/picke/domain/home/service/HomeService.java +++ b/src/main/java/com/swyp/picke/domain/home/service/HomeService.java @@ -21,7 +21,9 @@ import com.swyp.picke.domain.quiz.entity.QuizOption; import com.swyp.picke.domain.quiz.enums.QuizOptionLabel; import com.swyp.picke.domain.quiz.service.QuizService; +import com.swyp.picke.global.infra.s3.enums.FileCategory; import com.swyp.picke.global.infra.s3.service.S3PresignedUrlService; +import com.swyp.picke.global.infra.s3.util.ResourceUrlProvider; import java.util.Comparator; import java.util.List; import java.util.Objects; @@ -44,6 +46,7 @@ public class HomeService { private final PollService pollService; private final NotificationService notificationService; private final S3PresignedUrlService s3PresignedUrlService; + private final ResourceUrlProvider urlProvider; public HomeResponse getHome(Long userId) { boolean newNotice = false; @@ -139,7 +142,8 @@ private HomeTodayVoteResponse toTodayVote(Poll poll) { .thenComparing(option -> option.getId() == null ? Long.MAX_VALUE : option.getId())) .map(option -> new HomeTodayVoteOptionResponse( BattleOptionLabel.valueOf(option.getLabel().name()), - option.getTitle() + option.getTitle(), + urlProvider.getImageUrl(FileCategory.PHILOSOPHER, option.getImageUrl()) )) .toList(); diff --git a/src/main/java/com/swyp/picke/domain/poll/converter/PollConverter.java b/src/main/java/com/swyp/picke/domain/poll/converter/PollConverter.java index 784c03a6..e4deb562 100644 --- a/src/main/java/com/swyp/picke/domain/poll/converter/PollConverter.java +++ b/src/main/java/com/swyp/picke/domain/poll/converter/PollConverter.java @@ -8,14 +8,20 @@ import com.swyp.picke.domain.poll.dto.response.PollSimpleResponse; import com.swyp.picke.domain.poll.entity.Poll; import com.swyp.picke.domain.poll.entity.PollOption; +import com.swyp.picke.global.infra.s3.enums.FileCategory; +import com.swyp.picke.global.infra.s3.util.ResourceUrlProvider; import java.util.Comparator; import java.util.List; +import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; import org.springframework.stereotype.Component; @Component +@RequiredArgsConstructor public class PollConverter { + private final ResourceUrlProvider urlProvider; + private static final Comparator OPTION_SORTER = Comparator.comparing((PollOption option) -> option.getDisplayOrder() == null ? Integer.MAX_VALUE : option.getDisplayOrder()) .thenComparing(option -> option.getLabel() == null ? "" : option.getLabel().name()) @@ -83,7 +89,8 @@ private List toOptionResponses(List options) { option.getLabel(), option.getTitle(), option.getDisplayOrder(), - option.getVoteCount() + option.getVoteCount(), + urlProvider.getImageUrl(FileCategory.PHILOSOPHER, option.getImageUrl()) )) .toList(); } diff --git a/src/main/java/com/swyp/picke/domain/poll/dto/response/PollOptionResponse.java b/src/main/java/com/swyp/picke/domain/poll/dto/response/PollOptionResponse.java index b619a55f..a8a67ce1 100644 --- a/src/main/java/com/swyp/picke/domain/poll/dto/response/PollOptionResponse.java +++ b/src/main/java/com/swyp/picke/domain/poll/dto/response/PollOptionResponse.java @@ -7,7 +7,8 @@ public record PollOptionResponse( PollOptionLabel label, String title, Integer displayOrder, - Long voteCount + Long voteCount, + String imageUrl ) { } diff --git a/src/main/java/com/swyp/picke/domain/poll/entity/PollOption.java b/src/main/java/com/swyp/picke/domain/poll/entity/PollOption.java index d15ffffc..fa54ad75 100644 --- a/src/main/java/com/swyp/picke/domain/poll/entity/PollOption.java +++ b/src/main/java/com/swyp/picke/domain/poll/entity/PollOption.java @@ -38,19 +38,24 @@ public class PollOption extends BaseEntity { @Column(name = "vote_count", nullable = false) private Long voteCount; + @Column(name = "image_url", length = 500) + private String imageUrl; + @Builder - public PollOption(Poll poll, PollOptionLabel label, String title, Integer displayOrder, Long voteCount) { + public PollOption(Poll poll, PollOptionLabel label, String title, Integer displayOrder, Long voteCount, String imageUrl) { this.poll = poll; this.label = label; this.title = title; this.displayOrder = displayOrder; this.voteCount = voteCount == null ? 0L : voteCount; + this.imageUrl = imageUrl; } - public void update(String title, Integer displayOrder) { + public void update(String title, Integer displayOrder, String imageUrl) { if (title != null) this.title = title; if (displayOrder != null) this.displayOrder = displayOrder; + if (imageUrl != null) this.imageUrl = imageUrl; } public void increaseVoteCount() { diff --git a/src/main/java/com/swyp/picke/domain/poll/service/PollServiceImpl.java b/src/main/java/com/swyp/picke/domain/poll/service/PollServiceImpl.java index 7ac5e4b3..d447b6f1 100644 --- a/src/main/java/com/swyp/picke/domain/poll/service/PollServiceImpl.java +++ b/src/main/java/com/swyp/picke/domain/poll/service/PollServiceImpl.java @@ -127,6 +127,7 @@ public AdminPollDetailResponse createPoll(AdminPollCreateRequest request) { .label(optionRequest.label()) .title(optionRequest.title()) .displayOrder(displayOrder) + .imageUrl(optionRequest.imageUrl()) .build(); option = pollOptionRepository.save(option); savedOptions.add(option); @@ -169,10 +170,11 @@ public AdminPollDetailResponse updatePoll(Long pollId, AdminPollUpdateRequest re .label(optionRequest.label()) .title(optionRequest.title()) .displayOrder(displayOrder) + .imageUrl(optionRequest.imageUrl()) .build(); option = pollOptionRepository.save(option); } else { - option.update(optionRequest.title(), displayOrder); + option.update(optionRequest.title(), displayOrder, optionRequest.imageUrl()); } } diff --git a/src/main/resources/db/migration/V20260705_02__add_image_url_to_poll_options.sql b/src/main/resources/db/migration/V20260705_02__add_image_url_to_poll_options.sql new file mode 100644 index 00000000..e19f61c3 --- /dev/null +++ b/src/main/resources/db/migration/V20260705_02__add_image_url_to_poll_options.sql @@ -0,0 +1,3 @@ +-- Add image_url column to poll_options so pre-vote (사전투표) options can show a philosopher icon, +-- matching the existing battle_options.image_url column. +ALTER TABLE poll_options ADD COLUMN IF NOT EXISTS image_url VARCHAR(500); diff --git a/src/test/java/com/swyp/picke/domain/home/service/HomeServiceTest.java b/src/test/java/com/swyp/picke/domain/home/service/HomeServiceTest.java index 89eabe5f..39dd9d0d 100644 --- a/src/test/java/com/swyp/picke/domain/home/service/HomeServiceTest.java +++ b/src/test/java/com/swyp/picke/domain/home/service/HomeServiceTest.java @@ -19,6 +19,7 @@ import com.swyp.picke.domain.quiz.enums.QuizStatus; import com.swyp.picke.domain.quiz.service.QuizService; import com.swyp.picke.global.infra.s3.service.S3PresignedUrlService; +import com.swyp.picke.global.infra.s3.util.ResourceUrlProvider; import java.time.LocalDate; import java.util.List; import org.junit.jupiter.api.DisplayName; @@ -50,6 +51,9 @@ class HomeServiceTest { @Mock private S3PresignedUrlService s3PresignedUrlService; + @Mock + private ResourceUrlProvider urlProvider; + @InjectMocks private HomeService homeService; From aa449f044c88135a6053fb067eeb4f598bb49057 Mon Sep 17 00:00:00 2001 From: Youwol <153346797+si-zero@users.noreply.github.com> Date: Mon, 6 Jul 2026 09:40:20 +0900 Subject: [PATCH 21/29] =?UTF-8?q?#297=20[Fix]=20=EB=8C=93=EA=B8=80=20?= =?UTF-8?q?=EC=9E=91=EC=84=B1=20=EC=8B=9C=EA=B0=81=EC=9D=B4=209=EC=8B=9C?= =?UTF-8?q?=EA=B0=84=20=EC=A0=84=EC=9C=BC=EB=A1=9C=20=ED=91=9C=EC=8B=9C?= =?UTF-8?q?=EB=90=98=EB=8A=94=20=EB=B2=84=EA=B7=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/swyp/picke/PickeApplication.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/com/swyp/picke/PickeApplication.java b/src/main/java/com/swyp/picke/PickeApplication.java index c309634b..72b85f64 100644 --- a/src/main/java/com/swyp/picke/PickeApplication.java +++ b/src/main/java/com/swyp/picke/PickeApplication.java @@ -1,5 +1,6 @@ package com.swyp.picke; +import java.util.TimeZone; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.data.jpa.repository.config.EnableJpaAuditing; @@ -10,6 +11,7 @@ @SpringBootApplication public class PickeApplication { public static void main(String[] args) { + TimeZone.setDefault(TimeZone.getTimeZone("Asia/Seoul")); SpringApplication.run(PickeApplication.class, args); // 실행 클래스 수정완료 } } \ No newline at end of file From 3259a1a9fe5042d8cae79a81f87bf2cee379da6b Mon Sep 17 00:00:00 2001 From: Youwol <153346797+si-zero@users.noreply.github.com> Date: Mon, 6 Jul 2026 21:56:25 +0900 Subject: [PATCH 22/29] =?UTF-8?q?#301=20[Fix]=20robots.txt=20=ED=8C=8C?= =?UTF-8?q?=EC=9D=BC=20=EB=B6=80=EC=9E=AC=EB=A1=9C=20AdMob=20app-ads.txt?= =?UTF-8?q?=20=ED=81=AC=EB=A1=A4=EB=A7=81=20=EC=B0=A8=EB=8B=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/swyp/picke/global/config/SecurityConfig.java | 3 ++- src/main/resources/static/robots.txt | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 src/main/resources/static/robots.txt diff --git a/src/main/java/com/swyp/picke/global/config/SecurityConfig.java b/src/main/java/com/swyp/picke/global/config/SecurityConfig.java index bf407fc6..9f36b37a 100644 --- a/src/main/java/com/swyp/picke/global/config/SecurityConfig.java +++ b/src/main/java/com/swyp/picke/global/config/SecurityConfig.java @@ -50,7 +50,8 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { "/report/**", "/battle/**", "/.well-known/**", - "/app-ads.txt" + "/app-ads.txt", + "/robots.txt" ).permitAll() // 2. 관리자 HTML 화면 렌더링 요청 diff --git a/src/main/resources/static/robots.txt b/src/main/resources/static/robots.txt new file mode 100644 index 00000000..e9920dcb --- /dev/null +++ b/src/main/resources/static/robots.txt @@ -0,0 +1,2 @@ +User-agent: Google-adstxt +Disallow: From e91819b6749a6b869448760e8fbba5721e05ed94 Mon Sep 17 00:00:00 2001 From: Youwol <153346797+si-zero@users.noreply.github.com> Date: Tue, 7 Jul 2026 00:17:47 +0900 Subject: [PATCH 23/29] =?UTF-8?q?#305=20[Fix]=20S3=20=EC=98=A4=EB=94=94?= =?UTF-8?q?=EC=98=A4=20=EC=A1=B0=EA=B0=81=20=EC=9E=AC=EB=8B=A4=EC=9A=B4?= =?UTF-8?q?=EB=A1=9C=EB=93=9C=20=EC=8B=9C=20FileAlreadyExistsException?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=20TTS=20=ED=8C=8C=EC=9D=B4=ED=94=84=EB=9D=BC?= =?UTF-8?q?=EC=9D=B8=20=EC=8B=A4=ED=8C=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../picke/global/infra/s3/service/S3UploadServiceImpl.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/swyp/picke/global/infra/s3/service/S3UploadServiceImpl.java b/src/main/java/com/swyp/picke/global/infra/s3/service/S3UploadServiceImpl.java index e22c4e0b..89004aaa 100644 --- a/src/main/java/com/swyp/picke/global/infra/s3/service/S3UploadServiceImpl.java +++ b/src/main/java/com/swyp/picke/global/infra/s3/service/S3UploadServiceImpl.java @@ -80,9 +80,11 @@ public File downloadFile(String fileUrl) { // URL에서 순수 Key만 추출 String pureKey = fileUrl.contains(".com/") ? fileUrl.split(".com/")[1] : fileUrl; - // 다운로드 받을 로컬 임시 파일 생성 + // 다운로드 받을 로컬 임시 파일 경로 생성 File tempFile = File.createTempFile("s3_download_", ".mp3"); Path tempFilePath = tempFile.toPath(); + // getObject(request, path)는 대상 파일이 이미 존재하면 실패하므로, 생성된 빈 파일을 미리 삭제 + Files.delete(tempFilePath); // S3 다운로드 요청 GetObjectRequest getObjectRequest = GetObjectRequest.builder() From d64d5ca630b677f5b9b78d40f5b1187898d39f84 Mon Sep 17 00:00:00 2001 From: Youwol <153346797+si-zero@users.noreply.github.com> Date: Tue, 7 Jul 2026 00:41:15 +0900 Subject: [PATCH 24/29] =?UTF-8?q?#309=20[Fix]=20JwtFilter=20=EC=9E=90?= =?UTF-8?q?=EC=B2=B4=20=ED=99=94=EC=9D=B4=ED=8A=B8=EB=A6=AC=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=EC=97=90=20/robots.txt=20=EB=88=84=EB=9D=BD=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=20401=20=EB=B0=9C=EC=83=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/swyp/picke/domain/oauth/jwt/JwtFilter.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/swyp/picke/domain/oauth/jwt/JwtFilter.java b/src/main/java/com/swyp/picke/domain/oauth/jwt/JwtFilter.java index a1c51b41..f4c0b76a 100644 --- a/src/main/java/com/swyp/picke/domain/oauth/jwt/JwtFilter.java +++ b/src/main/java/com/swyp/picke/domain/oauth/jwt/JwtFilter.java @@ -46,7 +46,8 @@ public class JwtFilter extends OncePerRequestFilter { "/api/v1/share/recap/", "/.well-known", "/api/v1/resources", - "/app-ads.txt" + "/app-ads.txt", + "/robots.txt" ); @Override From d32d1beb67ad844f9acfdbe72733eb50c5955dab Mon Sep 17 00:00:00 2001 From: JOO Date: Tue, 7 Jul 2026 12:02:23 +0900 Subject: [PATCH 25/29] =?UTF-8?q?[Remove]=20=EB=AF=B8=EC=82=AC=EC=9A=A9=20?= =?UTF-8?q?=EB=A1=9C=EA=B7=B8=20=ED=8C=8C=EC=9D=BC=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hs_err_pid172944.log | 281 ------------------------------------------- hs_err_pid189152.log | 281 ------------------------------------------- hs_err_pid192028.log | 281 ------------------------------------------- 3 files changed, 843 deletions(-) delete mode 100644 hs_err_pid172944.log delete mode 100644 hs_err_pid189152.log delete mode 100644 hs_err_pid192028.log diff --git a/hs_err_pid172944.log b/hs_err_pid172944.log deleted file mode 100644 index 8707abc3..00000000 --- a/hs_err_pid172944.log +++ /dev/null @@ -1,281 +0,0 @@ -# -# There is insufficient memory for the Java Runtime Environment to continue. -# Native memory allocation (mmap) failed to map 532676608 bytes. Error detail: G1 virtual space -# Possible reasons: -# The system is out of physical RAM or swap space -# This process is running with CompressedOops enabled, and the Java Heap may be blocking the growth of the native heap -# Possible solutions: -# Reduce memory load on the system -# Increase physical memory or swap space -# Check if swap backing store is full -# Decrease Java heap size (-Xmx/-Xms) -# Decrease number of Java threads -# Decrease Java thread stack sizes (-Xss) -# Set larger code cache with -XX:ReservedCodeCacheSize= -# JVM is running with Zero Based Compressed Oops mode in which the Java heap is -# placed in the first 32GB address space. The Java Heap base address is the -# maximum limit for the native heap growth. Please use -XX:HeapBaseMinAddress -# to set the Java Heap base and to place the Java Heap above 32GB virtual address. -# This output file may be truncated or incomplete. -# -# Out of Memory Error (os_windows.cpp:3714), pid=172944, tid=186552 -# -# JRE version: (21.0.10+7) (build ) -# Java VM: OpenJDK 64-Bit Server VM (21.0.10+7-LTS, mixed mode, emulated-client, sharing, tiered, compressed oops, compressed class ptrs, g1 gc, windows-amd64) -# No core dump will be written. Minidumps are not enabled by default on client versions of Windows -# - ---------------- S U M M A R Y ------------ - -Command Line: -XX:TieredStopAtLevel=1 -Dspring.profiles.active=local -Dspring.output.ansi.enabled=always -Dcom.sun.management.jmxremote -Dspring.jmx.enabled=true -Dspring.liveBeansView.mbeanDomain -Dspring.application.admin.enabled=true -Dmanagement.endpoints.jmx.exposure.include=* -javaagent:C:\Users\guswn\AppData\Local\Programs\IntelliJ IDEA\lib\idea_rt.jar=51664 -Dfile.encoding=UTF-8 -Dsun.stdout.encoding=UTF-8 -Dsun.stderr.encoding=UTF-8 com.swyp.picke.PickeApplication - -Host: Intel(R) Core(TM) Ultra 5 125H, 18 cores, 31G, Windows 11 , 64 bit Build 26100 (10.0.26100.7920) -Time: Mon Mar 30 22:58:11 2026 elapsed time: 1.695367 seconds (0d 0h 0m 1s) - ---------------- T H R E A D --------------- - -Current thread (0x0000024510954d30): JavaThread "Unknown thread" [_thread_in_vm, id=186552, stack(0x0000007972f00000,0x0000007973000000) (1024K)] - -Stack: [0x0000007972f00000,0x0000007973000000] -Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code) -V [jvm.dll+0x6df2b9] -V [jvm.dll+0x8bbdeb] -V [jvm.dll+0x8be37a] -V [jvm.dll+0x8bea53] -V [jvm.dll+0x28a7a6] -V [jvm.dll+0x6dbc15] -V [jvm.dll+0x6cfbca] -V [jvm.dll+0x364f6e] -V [jvm.dll+0x36ce3b] -V [jvm.dll+0x3be8d9] -V [jvm.dll+0x3beb7b] -V [jvm.dll+0x339137] -V [jvm.dll+0x339c7b] -V [jvm.dll+0x88634e] -V [jvm.dll+0x3cb831] -V [jvm.dll+0x86f25c] -V [jvm.dll+0x45e901] -V [jvm.dll+0x460541] -C [jli.dll+0x52f0] -C [ucrtbase.dll+0x37b0] -C [KERNEL32.DLL+0x2e8d7] -C [ntdll.dll+0x8c48c] - - ---------------- P R O C E S S --------------- - -Threads class SMR info: -_java_thread_list=0x00007ffa227e2208, length=0, elements={ -} - -Java Threads: ( => current thread ) -Total: 0 - -Other Threads: - 0x00000245266f03f0 WorkerThread "GC Thread#0" [id=134476, stack(0x0000007973000000,0x0000007973100000) (1024K)] - 0x00000245109ce130 ConcurrentGCThread "G1 Main Marker" [id=195520, stack(0x0000007973100000,0x0000007973200000) (1024K)] - 0x00000245109d0570 WorkerThread "G1 Conc#0" [id=133400, stack(0x0000007973200000,0x0000007973300000) (1024K)] - -[error occurred during error reporting (printing all threads), id 0xc0000005, EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x00007ffa21edbbb7] -VM state: not at safepoint (not fully initialized) - -VM Mutex/Monitor currently owned by a thread: ([mutex/lock_event]) -[0x00007ffa228566b0] Heap_lock - owner thread: 0x0000024510954d30 - -Heap address: 0x0000000606800000, size: 8088 MB, Compressed Oops mode: Zero based, Oop shift amount: 3 - -CDS archive(s) mapped at: [0x0000000000000000-0x0000000000000000-0x0000000000000000), size 0, SharedBaseAddress: 0x0000000800000000, ArchiveRelocationMode: 1. -Narrow klass base: 0x0000000000000000, Narrow klass shift: 0, Narrow klass range: 0x0 - -GC Precious Log: - CardTable entry size: 512 - Card Set container configuration: InlinePtr #cards 4 size 8 Array Of Cards #cards 32 size 80 Howl #buckets 8 coarsen threshold 7372 Howl Bitmap #cards 1024 size 144 coarsen threshold 921 Card regions per heap region 1 cards per card region 8192 - -Heap: - garbage-first heap total 0K, used 0K [0x0000000606800000, 0x0000000800000000) - region size 4096K, 0 young (0K), 0 survivors (0K) - -[error occurred during error reporting (printing heap information), id 0xc0000005, EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x00007ffa222c9019] -GC Heap History (0 events): -No events - -Dll operation events (1 events): -Event: 0.007 Loaded shared library D:\application\.jdk\bin\java.dll - -Deoptimization events (0 events): -No events - -Classes loaded (0 events): -No events - -Classes unloaded (0 events): -No events - -Classes redefined (0 events): -No events - -Internal exceptions (0 events): -No events - -ZGC Phase Switch (0 events): -No events - -VM Operations (0 events): -No events - -Memory protections (0 events): -No events - -Nmethod flushes (0 events): -No events - -Events (0 events): -No events - - -Dynamic libraries: -0x00007ff7fbf60000 - 0x00007ff7fbf6e000 D:\application\.jdk\bin\java.exe -0x00007ffb03b00000 - 0x00007ffb03d67000 C:\WINDOWS\SYSTEM32\ntdll.dll -0x00007ffb02ce0000 - 0x00007ffb02da9000 C:\WINDOWS\System32\KERNEL32.DLL -0x00007ffb00fa0000 - 0x00007ffb01391000 C:\WINDOWS\System32\KERNELBASE.dll -0x00007ffb003e0000 - 0x00007ffb0052b000 C:\WINDOWS\System32\ucrtbase.dll -0x00007ffaeab10000 - 0x00007ffaeab2e000 D:\application\.jdk\bin\VCRUNTIME140.dll -0x00007ffae63b0000 - 0x00007ffae63c8000 D:\application\.jdk\bin\jli.dll -0x00007ffb02db0000 - 0x00007ffb02f75000 C:\WINDOWS\System32\USER32.dll -0x00007ffae7290000 - 0x00007ffae7523000 C:\WINDOWS\WinSxS\amd64_microsoft.windows.common-controls_6595b64144ccf1df_6.0.26100.8037_none_3e092faae333b53b\COMCTL32.dll -0x00007ffb031a0000 - 0x00007ffb03249000 C:\WINDOWS\System32\msvcrt.dll -0x00007ffb015c0000 - 0x00007ffb015e7000 C:\WINDOWS\System32\win32u.dll -0x00007ffb02780000 - 0x00007ffb027ab000 C:\WINDOWS\System32\GDI32.dll -0x00007ffb01770000 - 0x00007ffb0189b000 C:\WINDOWS\System32\gdi32full.dll -0x00007ffb005f0000 - 0x00007ffb00693000 C:\WINDOWS\System32\msvcp_win.dll -0x00007ffb03160000 - 0x00007ffb03191000 C:\WINDOWS\System32\IMM32.DLL -0x00007ffaecfa0000 - 0x00007ffaecfac000 D:\application\.jdk\bin\vcruntime140_1.dll -0x00007ffad39c0000 - 0x00007ffad3a49000 D:\application\.jdk\bin\msvcp140.dll -0x00007ffa21b90000 - 0x00007ffa22938000 D:\application\.jdk\bin\server\jvm.dll -0x00007ffb01d30000 - 0x00007ffb01deb000 C:\WINDOWS\System32\ADVAPI32.dll -0x00007ffb03250000 - 0x00007ffb032f7000 C:\WINDOWS\System32\sechost.dll -0x00007ffb024a0000 - 0x00007ffb025b8000 C:\WINDOWS\System32\RPCRT4.dll -0x00007ffb029a0000 - 0x00007ffb02a14000 C:\WINDOWS\System32\WS2_32.dll -0x00007ffb00240000 - 0x00007ffb0029e000 C:\WINDOWS\SYSTEM32\POWRPROF.dll -0x00007ffaec6c0000 - 0x00007ffaec6f5000 C:\WINDOWS\SYSTEM32\WINMM.dll -0x00007ffae7a30000 - 0x00007ffae7a3b000 C:\WINDOWS\SYSTEM32\VERSION.dll -0x00007ffb00220000 - 0x00007ffb00234000 C:\WINDOWS\SYSTEM32\UMPDC.dll -0x00007ffaff170000 - 0x00007ffaff18b000 C:\WINDOWS\SYSTEM32\kernel.appcore.dll -0x00007ffaea260000 - 0x00007ffaea26a000 D:\application\.jdk\bin\jimage.dll -0x00007ffafe4f0000 - 0x00007ffafe732000 C:\WINDOWS\SYSTEM32\DBGHELP.DLL -0x00007ffb01e50000 - 0x00007ffb021d2000 C:\WINDOWS\System32\combase.dll -0x00007ffb02f80000 - 0x00007ffb03057000 C:\WINDOWS\System32\OLEAUT32.dll -0x00007ffada3d0000 - 0x00007ffada40b000 C:\WINDOWS\SYSTEM32\dbgcore.DLL -0x00007ffb013a0000 - 0x00007ffb01445000 C:\WINDOWS\System32\bcryptPrimitives.dll -0x00007ffae63a0000 - 0x00007ffae63b0000 D:\application\.jdk\bin\instrument.dll -0x00007ffae6310000 - 0x00007ffae6331000 D:\application\.jdk\bin\java.dll - -JVMTI agents: -C:\Users\guswn\AppData\Local\Programs\IntelliJ IDEA\lib\idea_rt.jar path:none, loaded, not initialized, instrumentlib options:51664 - -dbghelp: loaded successfully - version: 4.0.5 - missing functions: none -symbol engine: initialized successfully - sym options: 0x614 - pdb path: .;D:\application\.jdk\bin;C:\WINDOWS\SYSTEM32;C:\WINDOWS\WinSxS\amd64_microsoft.windows.common-controls_6595b64144ccf1df_6.0.26100.8037_none_3e092faae333b53b;D:\application\.jdk\bin\server - -VM Arguments: -jvm_args: -XX:TieredStopAtLevel=1 -Dspring.profiles.active=local -Dspring.output.ansi.enabled=always -Dcom.sun.management.jmxremote -Dspring.jmx.enabled=true -Dspring.liveBeansView.mbeanDomain -Dspring.application.admin.enabled=true -Dmanagement.endpoints.jmx.exposure.include=* -javaagent:C:\Users\guswn\AppData\Local\Programs\IntelliJ IDEA\lib\idea_rt.jar=51664 -Dfile.encoding=UTF-8 -Dsun.stdout.encoding=UTF-8 -Dsun.stderr.encoding=UTF-8 -java_command: com.swyp.picke.PickeApplication -java_class_path (initial): D:\Desktop\project\Server\build\classes\java\main;D:\Desktop\project\Server\build\resources\main;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.projectlombok\lombok\1.18.42\8365263844ebb62398e0dc33057ba10ba472d3b8\lombok-1.18.42.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter-web\3.5.11\68fde4c94249e92526105a93ac7c22bd89b6945e\spring-boot-starter-web-3.5.11.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springdoc\springdoc-openapi-starter-webmvc-ui\2.8.16\61c68f705d3f17e8318fb18b2904fa6368af251c\springdoc-openapi-starter-webmvc-ui-2.8.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter-validation\3.5.11\903eefb6eab302617b0f01cc6d65664343bff2a7\spring-boot-starter-validation-3.5.11.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter-data-jpa\3.5.11\f176e5c643720818ec7910e1dd2ccb402411cc5d\spring-boot-starter-data-jpa-3.5.11.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter-security\3.5.11\db8b6b7951883dea3ce7404f20d6816104cedd4e\spring-boot-starter-security-3.5.11.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.jsonwebtoken\jjwt-api\0.12.6\478886a888f6add04937baf0361144504a024967\jjwt-api-0.12.6.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter-webflux\3.5.11\1461f9a6b6b8397ad71a98c9bbf4278159fb9624\spring-boot-starter-webflux-3.5.11.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.crypto.tink\apps-rewardedads\1.9.1\cbaf11457b36fe57d90a5cb16a76833906486503\apps-rewardedads-1.9.1.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.cloud\google-cloud-texttospeech\2.58.0\9be37bd3c81c14c72c9cbcfa2dfaf6dad7a35075\google-cloud-texttospeech-2.58.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.awspring.cloud\spring-cloud-aws-starter-s3\3.3.0\fa9790f990ab540814aafdbf2e97c8cd53b5b1a6\spring-cloud-aws-starter-s3-3.3.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter-thymeleaf\3.5.11\d997aa0df579cf43507d425057940e2712e44808\spring-boot-starter-thymeleaf-3.5.11.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter-json\3.5.11\4cdcd68dcddf0a4c645166e39c3fe448fe2b8e98\spring-boot-starter-json-3.5.11.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter\3.5.11\10ce971300fd56d6be5f1cfe7d27ddfb1ed7158d\spring-boot-starter-3.5.11.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter-tomcat\3.5.11\fb7b96cb61e5fd5700aed96194562e32d166b5ef\spring-boot-starter-tomcat-3.5.11.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework\spring-webmvc\6.2.16\ff2db80406f1459fddd14a8d06d57e0e3ab69465\spring-webmvc-6.2.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework\spring-web\6.2.16\2c4355f1f7e5b8969f696cbc90f25cc22f0f2164\spring-web-6.2.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springdoc\springdoc-openapi-starter-webmvc-api\2.8.16\6e41988d84978e529c01a4cc052b761cd27d5b90\springdoc-openapi-starter-webmvc-api-2.8.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.webjars\swagger-ui\5.32.0\d04c7e3e5b8616813136fa36382a548751775528\swagger-ui-5.32.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.webjars\webjars-locator-lite\1.1.3\217ce590453251b39b72c4a9af3986998f6fdbd9\webjars-locator-lite-1.1.3.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.apache.tomcat.embed\tomcat-embed-el\10.1.52\cd94ce17c5a9937eca365eb494711efa10d49b86\tomcat-embed-el-10.1.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.hibernate.validator\hibernate-validator\8.0.3.Final\4425f554297a1c5ba03a3f30e559a9fd91048cf8\hibernate-validator-8.0.3.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter-jdbc\3.5.11\3ce801963caadf6eb29abd68f5a0fe50c9bfe211\spring-boot-starter-jdbc-3.5.11.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.hibernate.orm\hibernate-core\6.6.42.Final\996e3df4a6c67941b582e4493cb9a39c83198f1e\hibernate-core-6.6.42.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.data\spring-data-jpa\3.5.9\56081dde4f663db74ba000c1f8ab30673058c363\spring-data-jpa-3.5.9.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework\spring-aspects\6.2.16\763140a66821c494985533f29280a3b4132cf055\spring-aspects-6.2.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.security\spring-security-web\6.5.8\3db7bf41191d5b23493cca6252595405b5112b34\spring-security-web-6.5.8.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.security\spring-security-config\6.5.8\302d32eba89131c0ffd15ba0a1e465051336d42f\spring-security-config-6.5.8.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework\spring-aop\6.2.16\59250efa248420a114fe23b4ccf2fea46b804186\spring-aop-6.2.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework\spring-webflux\6.2.16\699ef8bc182893f9ed43206d372f20c4f9aa3231\spring-webflux-6.2.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter-reactor-netty\3.5.11\f98bd3e3019078679dec4f21fb63152aa2e059a7\spring-boot-starter-reactor-netty-3.5.11.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.crypto.tink\tink\1.10.0\84771b1a4bb5726f73fb8490fadb23f1d2aacd38\tink-1.10.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.code.gson\gson\2.13.2\48b8230771e573b54ce6e867a9001e75977fe78e\gson-2.13.2.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.http-client\google-http-client\1.45.3\dde98b597081b98514867c9cefa551fcdea3a28c\google-http-client-1.45.3.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.errorprone\error_prone_annotations\2.41.0\4381275efdef6ddfae38f002c31e84cd001c97f0\error_prone_annotations-2.41.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.opencensus\opencensus-contrib-http-util\0.31.1\3c13fc5715231fadb16a9b74a44d9d59c460cfa8\opencensus-contrib-http-util-0.31.1.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.guava\guava\33.4.0-jre\3fcc0a259f724c7de54a6a55ea7e26d3d5c0cac\guava-33.4.0-jre.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.grpc\grpc-api\1.69.0\965c2c7f708cd6e6ddbf1eb175c3e87e96e41297\grpc-api-1.69.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.code.findbugs\jsr305\3.0.2\25ea2e8b0c338a877313bd4672d3fe056ea78f0d\jsr305-3.0.2.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.grpc\grpc-stub\1.69.0\9e7dc30a9c2df70e25ef4b941f46187e6e178e7a\grpc-stub-1.69.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.grpc\grpc-protobuf\1.69.0\2990b4948357d4fe46aaecb47290cff102079f1e\grpc-protobuf-1.69.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.api\api-common\2.43.0\963d97d95e9bf7275cc26f0b6b72e2aa5b92c6fd\api-common-2.43.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.auto.value\auto-value-annotations\1.11.0\f0d047931d07cfbc6fa4079854f181ff62891d6f\auto-value-annotations-1.11.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\javax.annotation\javax.annotation-api\1.3.2\934c04d3cfef185a8008e7bf34331b79730a9d43\javax.annotation-api-1.3.2.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.j2objc\j2objc-annotations\3.0.0\7399e65dd7e9ff3404f4535b2f017093bdb134c7\j2objc-annotations-3.0.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.protobuf\protobuf-java\3.25.5\5ae5c9ec39930ae9b5a61b32b93288818ec05ec1\protobuf-java-3.25.5.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.api.grpc\proto-google-common-protos\2.51.0\ead75a32e6fd65740b6a69feb658254aeab3fef0\proto-google-common-protos-2.51.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.api.grpc\proto-google-cloud-texttospeech-v1\2.58.0\42f1f29876ddfa2523ebcc41dae801195fd8b3ce\proto-google-cloud-texttospeech-v1-2.58.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.api.grpc\proto-google-cloud-texttospeech-v1beta1\0.147.0\576df432a2c1181deabf21a54fdecc1a32f69f4e\proto-google-cloud-texttospeech-v1beta1-0.147.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.guava\failureaccess\1.0.2\c4a06a64e650562f30b7bf9aaec1bfed43aca12b\failureaccess-1.0.2.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.guava\listenablefuture\9999.0-empty-to-avoid-conflict-with-guava\b421526c5f297295adef1c886e5246c39d4ac629\listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.checkerframework\checker-qual\3.48.4\6b5d69a61012211d581e68699baf3beb1fd382da\checker-qual-3.48.4.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.api\gax\2.60.0\2d277e0795cb69bc14e03be068aa002539e3ef49\gax-2.60.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.auth\google-auth-library-credentials\1.31.0\b9cd5346d3a683d9a8d9786453f2419cc832a97f\google-auth-library-credentials-1.31.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.opencensus\opencensus-api\0.31.1\66a60c7201c2b8b20ce495f0295b32bb0ccbbc57\opencensus-api-0.31.1.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.grpc\grpc-context\1.69.0\cea23878872f76418dcd6df0c6eef0bf27463537\grpc-context-1.69.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.auth\google-auth-library-oauth2-http\1.31.0\df5be46d21b983aab8d0250f19b585a94bdedcde\google-auth-library-oauth2-http-1.31.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.api\gax-grpc\2.60.0\ca4d7dc8c2a85fbdba25ff3449726852e2359ae9\gax-grpc-2.60.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.grpc\grpc-inprocess\1.69.0\8ac4d2e13b48bed9624b8bc485c90f3d28820c93\grpc-inprocess-1.69.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.grpc\grpc-core\1.69.0\7dad3419dfb91a77788afcdf79e0477172784910\grpc-core-1.69.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.grpc\grpc-alts\1.69.0\6d1eac6726fd6fd177666c10fd154823b82272eb\grpc-alts-1.69.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.grpc\grpc-grpclb\1.69.0\d2c9c066693ce94805a503bc47f5b1e76f51541c\grpc-grpclb-1.69.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.conscrypt\conscrypt-openjdk-uber\2.5.2\d858f142ea189c62771c505a6548d8606ac098fe\conscrypt-openjdk-uber-2.5.2.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.grpc\grpc-auth\1.69.0\a75e19b20bb732364bdcc0979e9d7c9baa4e408e\grpc-auth-1.69.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.grpc\grpc-netty-shaded\1.69.0\99aa9789172695a4b09fe2af5f5bd0ab1be4ae85\grpc-netty-shaded-1.69.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.api\gax-httpjson\2.60.0\131d9283925337406e35561ec17bf326a9ecec1a\gax-httpjson-2.60.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.apache.httpcomponents\httpclient\4.5.14\1194890e6f56ec29177673f2f12d0b8e627dec98\httpclient-4.5.14.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\commons-codec\commons-codec\1.18.0\ee45d1cf6ec2cc2b809ff04b4dc7aec858e0df8f\commons-codec-1.18.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.apache.httpcomponents\httpcore\4.4.16\51cf043c87253c9f58b539c9f7e44c8894223850\httpcore-4.4.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.http-client\google-http-client-gson\1.45.3\29eba40245c4a4e5466f8764bd894d6a97c6694f\google-http-client-gson-1.45.3.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.protobuf\protobuf-java-util\3.25.5\38cc5ce479603e36466feda2a9f1dfdb2210ef00\protobuf-java-util-3.25.5.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.threeten\threetenbp\1.7.0\8703e893440e550295aa358281db468625bc9a05\threetenbp-1.7.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.awspring.cloud\spring-cloud-aws-starter\3.3.0\7d82d320cb1851beca3005eab2e484a38bd58a08\spring-cloud-aws-starter-3.3.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.awspring.cloud\spring-cloud-aws-s3\3.3.0\661e2914e3ad6555e20ffa262a9987c15bcc1712\spring-cloud-aws-s3-3.3.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.slf4j\slf4j-api\2.0.17\d9e58ac9c7779ba3bf8142aff6c830617a7fe60f\slf4j-api-2.0.17.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.thymeleaf\thymeleaf-spring6\3.1.3.RELEASE\4b276ea2bd536a18e44b40ff1d9f4848965ff59c\thymeleaf-spring6-3.1.3.RELEASE.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.fasterxml.jackson.datatype\jackson-datatype-jdk8\2.19.4\90d304bcdb1a4bacb6f4347be625d75300973c60\jackson-datatype-jdk8-2.19.4.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.fasterxml.jackson.datatype\jackson-datatype-jsr310\2.19.4\3cbcf2e636a6b062772299bf19a347536e58c4df\jackson-datatype-jsr310-2.19.4.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.fasterxml.jackson.module\jackson-module-parameter-names\2.19.4\502dfea4c83502f444837b3d040a51e8475f15f2\jackson-module-parameter-names-2.19.4.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.fasterxml.jackson.core\jackson-databind\2.19.4\7a39bf9257b726b90b80f27fa3f5174bc75162a5\jackson-databind-2.19.4.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-autoconfigure\3.5.11\3c7d2ec2ac3c301e95814e37fed1c86c19927fc4\spring-boot-autoconfigure-3.5.11.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot\3.5.11\8b7f6df00bfbe74d370e1d05d985a127884d2a9c\spring-boot-3.5.11.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter-logging\3.5.11\62b692ed7aee31a5670796be8b07732b6b836f4e\spring-boot-starter-logging-3.5.11.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\jakarta.annotation\jakarta.annotation-api\2.1.1\48b9bda22b091b1f48b13af03fe36db3be6e1ae3\jakarta.annotation-api-2.1.1.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework\spring-core\6.2.16\a73937f20a303e057add523915b48eb7901e1848\spring-core-6.2.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.yaml\snakeyaml\2.4\e0666b825b796f85521f02360e77f4c92c5a7a07\snakeyaml-2.4.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.apache.tomcat.embed\tomcat-embed-websocket\10.1.52\9d32b801fb474306349013fcdd8317c8cb4d739e\tomcat-embed-websocket-10.1.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.apache.tomcat.embed\tomcat-embed-core\10.1.52\f512bef2796b51299f4752f95918982c3003131d\tomcat-embed-core-10.1.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework\spring-context\6.2.16\caeae6bd50832d6ab28f707aa740e957401a5c20\spring-context-6.2.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework\spring-beans\6.2.16\990289064c810be71630fca9da8e2b6fe8f897b5\spring-beans-6.2.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework\spring-expression\6.2.16\e293ab797b1698084e56ae1f2362b315148683f6\spring-expression-6.2.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.micrometer\micrometer-observation\1.15.9\edf37b25cdfac0704d6fefa4543edb3ed1817eb0\micrometer-observation-1.15.9.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springdoc\springdoc-openapi-starter-common\2.8.16\5b702cb484981b42cfb455bd80b6ce7f49d34210\springdoc-openapi-starter-common-2.8.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.jspecify\jspecify\1.0.0\7425a601c1c7ec76645a78d22b8c6a627edee507\jspecify-1.0.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\jakarta.validation\jakarta.validation-api\3.0.2\92b6631659ba35ca09e44874d3eb936edfeee532\jakarta.validation-api-3.0.2.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.jboss.logging\jboss-logging\3.6.2.Final\3e0a139d7a74cc13b5e01daa8aaa7f71dccd577e\jboss-logging-3.6.2.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.fasterxml\classmate\1.7.3\f61c7e7b81e9249b0f6a05914eff9d54fb09f4a0\classmate-1.7.3.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.zaxxer\HikariCP\6.3.3\7c5aec1e47a97ff40977e0193018865304ea9585\HikariCP-6.3.3.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework\spring-jdbc\6.2.16\addfdde7b3212f34c95d791c37bb04ba4b08a1b7\spring-jdbc-6.2.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\jakarta.persistence\jakarta.persistence-api\3.1.0\66901fa1c373c6aff65c13791cc11da72060a8d6\jakarta.persistence-api-3.1.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\jakarta.transaction\jakarta.transaction-api\2.0.1\51a520e3fae406abb84e2e1148e6746ce3f80a1a\jakarta.transaction-api-2.0.1.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.data\spring-data-commons\3.5.9\6b577c71f563e78a7da984a3d572fde8a4df8103\spring-data-commons-3.5.9.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework\spring-orm\6.2.16\44b3cfb2c046440f83729641c929c405dc7f2c89\spring-orm-6.2.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework\spring-tx\6.2.16\5f9d6e78b76530e6258de8a0dff991fb1ad4b9b0\spring-tx-6.2.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.antlr\antlr4-runtime\4.13.0\5a02e48521624faaf5ff4d99afc88b01686af655\antlr4-runtime-4.13.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.aspectj\aspectjweaver\1.9.25.1\a713c790da4d794c7dfb542b550d4e44898d5e23\aspectjweaver-1.9.25.1.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.security\spring-security-core\6.5.8\d052dca52e49d95d2b03f81ae4b6762eeb4c78d0\spring-security-core-6.5.8.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.projectreactor\reactor-core\3.7.16\dc7f2ba3c4fbc69678937dfe1ad45264d8a1c7be\reactor-core-3.7.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.projectreactor.netty\reactor-netty-http\1.2.15\b20bb13c95b44f1d0c148bdf1197b7d4a7e0f278\reactor-netty-http-1.2.15.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.awspring.cloud\spring-cloud-aws-autoconfigure\3.3.0\b5a0b27e91ee997f8c86e4b0c521858fdcb9dc9b\spring-cloud-aws-autoconfigure-3.3.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.awspring.cloud\spring-cloud-aws-core\3.3.0\3c501426267d8ccbaaebc9796bd5de5bc5d0702e\spring-cloud-aws-core-3.3.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\s3\2.29.52\db65bc6177b0c4514be1f9775cb2094e29e85d3c\s3-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.thymeleaf\thymeleaf\3.1.3.RELEASE\51474f2a90b282ee97dabcd159c7faf24790f373\thymeleaf-3.1.3.RELEASE.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.fasterxml.jackson.core\jackson-core\2.19.4\a720ca9b800742699e041c3890f3731fe516085e\jackson-core-2.19.4.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.fasterxml.jackson.core\jackson-annotations\2.19.4\bbb09b1e7f7f5108890270eb701cb3ddef991c05\jackson-annotations-2.19.4.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\ch.qos.logback\logback-classic\1.5.32\2b1042c50f508f2eb402bd4d22ccbdf94cc37d2e\logback-classic-1.5.32.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.apache.logging.log4j\log4j-to-slf4j\2.24.3\da1143e2a2531ee1c2d90baa98eb50a28a39d5a7\log4j-to-slf4j-2.24.3.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.slf4j\jul-to-slf4j\2.0.17\524cb6ccc2b68a57604750e1ab8b13b5a786a6aa\jul-to-slf4j-2.0.17.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework\spring-jcl\6.2.16\8af6546d28815be574f384dceb93d248e9934f90\spring-jcl-6.2.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.micrometer\micrometer-commons\1.15.9\5a38f43cdc79a309a458c8ce130fff30a2a7f59\micrometer-commons-1.15.9.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.swagger.core.v3\swagger-core-jakarta\2.2.43\500566364be54e3556bcec28922a41ca5fcc7dcd\swagger-core-jakarta-2.2.43.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.security\spring-security-crypto\6.5.8\aec1a6f6c0e06be9dff08b11e8e1f457afca44b2\spring-security-crypto-6.5.8.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.reactivestreams\reactive-streams\1.0.4\3864a1320d97d7b045f729a326e1e077661f31b7\reactive-streams-1.0.4.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.projectreactor.netty\reactor-netty-core\1.2.15\94b2ca82f310c1bf31d3038060e4572eeca1d4b2\reactor-netty-core-1.2.15.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-codec-http2\4.1.131.Final\2e4c47131c60e0bbbca067c891597b466f7033ba\netty-codec-http2-4.1.131.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-codec-http\4.1.131.Final\253d80637ed689ed309ca62371e5fb97746b165\netty-codec-http-4.1.131.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-resolver-dns-native-macos\4.1.131.Final\9e4a908c073e56caa4127f54d946e3e9a5208506\netty-resolver-dns-native-macos-4.1.131.Final-osx-x86_64.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-resolver-dns\4.1.131.Final\7714c0babe26712ccfdbc158aa64898ab909e7d8\netty-resolver-dns-4.1.131.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-transport-native-epoll\4.1.131.Final\10b7a905019c1ad5c37e8cf63d7229fb00668c1d\netty-transport-native-epoll-4.1.131.Final-linux-x86_64.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\aws-core\2.29.52\dcfa86ac727b5d4e0abad1e8b025ac2febb6382e\aws-core-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\auth\2.29.52\76f9b22a99b0de0fd31447db22a5cba4ed4b172e\auth-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\regions\2.29.52\270b31c8695739d495452d380d036c72698e623\regions-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\aws-xml-protocol\2.29.52\e7290d4528affec022bd2f3739853f774a955ac2\aws-xml-protocol-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\protocol-core\2.29.52\1a0e4a114c0943142ca395000a949ee840890fea\protocol-core-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\sdk-core\2.29.52\3f058b489fac3d091417339e02b165e72c637f61\sdk-core-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\arns\2.29.52\879712423589b58434b8831b9b75304a16983178\arns-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\profiles\2.29.52\59dd1368bff2d242d84515ec7ea8fe63bb472c4e\profiles-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\crt-core\2.29.52\6a16e04be0e8bb8a1767e0644c631dadddfdd764\crt-core-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\http-auth\2.29.52\aa4ce3ff7bcd8dcf131a4f5445455b3eb4926dcf\http-auth-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\http-auth-aws\2.29.52\1d0dbfa072bc46207066ffa498ad4ed65c52ac6d\http-auth-aws-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\http-auth-spi\2.29.52\4a64e68a88e3eef0b51819f742931f3607cdd996\http-auth-spi-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\identity-spi\2.29.52\d18449651e8798398cadab6c4b5d8594bb0281c\identity-spi-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\checksums\2.29.52\90631313060ff8ef1ab7745bb1e9740913bdcefc\checksums-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\retries-spi\2.29.52\7e2c7ad44106799491de8cced5925b6473d62e4b\retries-spi-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\http-client-spi\2.29.52\a8da4f289736c702ec6664836761412e7e1e54a2\http-client-spi-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\metrics-spi\2.29.52\92c3797208d24b2b25ab9b6d1bbab624c3af1b9c\metrics-spi-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\json-utils\2.29.52\d88c6c03061b9f3fcd17dc8456365dab67cc1597\json-utils-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\utils\2.29.52\bde94a15cd79b0240bfa10230970e2f0e4c51eba\utils-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\checksums-spi\2.29.52\537363296f035a935b7d3b50a5bef90014d38010\checksums-spi-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\endpoints-spi\2.29.52\bd702a44ad440628af93afa1ec1d7cdc56baec67\endpoints-spi-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\annotations\2.29.52\9fa958ce528b57d90db01c5015daaf7bd373e57f\annotations-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.attoparser\attoparser\2.0.7.RELEASE\e5d0e988d9124139d645bb5872b24dfa23e283cc\attoparser-2.0.7.RELEASE.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.unbescape\unbescape\1.1.6.RELEASE\7b90360afb2b860e09e8347112800d12c12b2a13\unbescape-1.1.6.RELEASE.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\ch.qos.logback\logback-core\1.5.32\fdfb3ff9a842303d4a95207294a6c6bc64e2605d\logback-core-1.5.32.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.apache.logging.log4j\log4j-api\2.24.3\b02c125db8b6d295adf72ae6e71af5d83bce2370\log4j-api-2.24.3.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.swagger.core.v3\swagger-models-jakarta\2.2.43\a68f7470eb763609878460272000f260eabc24dc\swagger-models-jakarta-2.2.43.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.fasterxml.jackson.dataformat\jackson-dataformat-yaml\2.19.4\500956daea0869bf753b94fdaa77e5dc99847d79\jackson-dataformat-yaml-2.19.4.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.apache.commons\commons-lang3\3.17.0\b17d2136f0460dcc0d2016ceefca8723bdf4ee70\commons-lang3-3.17.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.swagger.core.v3\swagger-annotations-jakarta\2.2.43\dbd40253251deabb7a628a54b4550dc4fb492f4\swagger-annotations-jakarta-2.2.43.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\jakarta.xml.bind\jakarta.xml.bind-api\4.0.4\d6d2327f3817d9a33a3b6b8f2e15a96bc2e7afdc\jakarta.xml.bind-api-4.0.4.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-handler-proxy\4.1.131.Final\5ff9e74613a9dd3ca078f06880a16c8cdc046de0\netty-handler-proxy-4.1.131.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-handler\4.1.131.Final\5ca67999f41c0a68f0b66485ceb990683a0b0694\netty-handler-4.1.131.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-codec\4.1.131.Final\1874341f7b29879c6833c17e7305272f0cdc2cb6\netty-codec-4.1.131.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-transport\4.1.131.Final\474862e0855d7a9828fab06a9c73c05387604ee3\netty-transport-4.1.131.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-buffer\4.1.131.Final\f97b636ecd9b81ae3fd1d039b69c4fd3959ecf\netty-buffer-4.1.131.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-common\4.1.131.Final\cdc659109da226b698a74b543a5b97dd0f7e6959\netty-common-4.1.131.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-resolver-dns-classes-macos\4.1.131.Final\b9d57038cc4144e36aee5898085b7f1f018d2c9f\netty-resolver-dns-classes-macos-4.1.131.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-codec-dns\4.1.131.Final\cd23e12e5c3448a1b12c8a4b8deeb4faeb5e483e\netty-codec-dns-4.1.131.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-resolver\4.1.131.Final\9db1bfd7c57b9b6aa9b5cfc61fc3304594bb6b39\netty-resolver-4.1.131.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-transport-classes-epoll\4.1.131.Final\4d7848ac709491fb14f8bce2796fc3eff4a04fd6\netty-transport-classes-epoll-4.1.131.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-transport-native-unix-common\4.1.131.Final\fa975e4751b23d50c0a60569829f31944d11d292\netty-transport-native-unix-common-4.1.131.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\retries\2.29.52\48cb57817dd88977ec71e63550673c5ce010a191\retries-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.eventstream\eventstream\1.0.1\6ff8649dffc5190366ada897ba8525a836297784\eventstream-1.0.1.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\http-auth-aws-eventstream\2.29.52\e8b723c48008bcac96e2cc34c7415bd8b581c601\http-auth-aws-eventstream-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\aws-query-protocol\2.29.52\672d7a2df481414d02eedf3a9eff45fb87f1b8a\aws-query-protocol-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\third-party-jackson-core\2.29.52\82ff600d837e83130502775a1555c45d7a3e2e1\third-party-jackson-core-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\jakarta.activation\jakarta.activation-api\2.1.4\9e5c2a0d75dde71a0bedc4dbdbe47b78a5dc50f8\jakarta.activation-api-2.1.4.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-codec-socks\4.1.131.Final\614eacc17f44d8abaeaea81f210b4980c3568262\netty-codec-socks-4.1.131.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-devtools\3.5.11\fe7dfcaf3153d049909a618a7ba7df288e80f090\spring-boot-devtools-3.5.11.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.jsonwebtoken\jjwt-impl\0.12.6\ac23673a84b6089e0369fb8ab2c69edd91cd6eb0\jjwt-impl-0.12.6.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.jsonwebtoken\jjwt-jackson\0.12.6\f141e0c1136ba17f2632858238a31ae05642dbf8\jjwt-jackson-0.12.6.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.postgresql\postgresql\42.7.10\35100a3f0899551e27af8fed4a3414619a4663b3\postgresql-42.7.10.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.h2database\h2\2.3.232\4fcc05d966ccdb2812ae8b9a718f69226c0cf4e2\h2-2.3.232.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.grpc\grpc-protobuf-lite\1.69.0\91711f27421babf868e424a64426fccb9e8bf6ec\grpc-protobuf-lite-1.69.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.checkerframework\checker-qual\3.52.0\9c17f496846ab1fca8975c6a50ceac0b3bbe63f0\checker-qual-3.52.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.android\annotations\4.1.1.4\a1678ba907bf92691d879fef34e1a187038f9259\annotations-4.1.1.4.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.codehaus.mojo\animal-sniffer-annotations\1.24\aa9ba58d30e0aad7f1808fce9c541ea3760678d8\animal-sniffer-annotations-1.24.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.grpc\grpc-util\1.69.0\1929ab12fce0c610d9d7229b8767f6abb09ebd51\grpc-util-1.69.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.perfmark\perfmark-api\0.27.0\f86f575a41b091786a4b027cd9c0c1d2e3fc1c01\perfmark-api-0.27.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.grpc\grpc-googleapis\1.69.0\1c11a033d96689a4bf3c92fe89b35f5edaef10c2\grpc-googleapis-1.69.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.grpc\grpc-xds\1.69.0\fa1d282a8ba3ae2a5dc0205d2f6a18b5606b5b62\grpc-xds-1.69.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.grpc\grpc-services\1.69.0\bcd917dad2380ee7cf4728da33816ffb9fad6b8b\grpc-services-1.69.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.re2j\re2j\1.7\2949632c1b4acce0d7784f28e3152e9cf3c2ec7a\re2j-1.7.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.hibernate.common\hibernate-commons-annotations\7.0.3.Final\e183c4be8bb41d12e9f19b374e00c34a0a85f439\hibernate-commons-annotations-7.0.3.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.smallrye\jandex\3.2.0\f17ad860f62a08487b9edabde608f8ac55c62fa7\jandex-3.2.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\net.bytebuddy\byte-buddy\1.17.8\af5735f63d00ca47a9375fae5c7471a36331c6ed\byte-buddy-1.17.8.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.glassfish.jaxb\jaxb-runtime\4.0.6\fb95ebb62564657b2fedfe165b859789ef3a8711\jaxb-runtime-4.0.6.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\jakarta.inject\jakarta.inject-api\2.0.1\4c28afe1991a941d7702fe1362c365f0a8641d1e\jakarta.inject-api-2.0.1.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.glassfish.jaxb\jaxb-core\4.0.6\8e61282303777fc98a00cc3affd0560d68748a75\jaxb-core-4.0.6.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\apache-client\2.29.52\b7ce213c946d69ab1807b3f7ecac1ce29ed60485\apache-client-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\netty-nio-client\2.29.52\20fa79ba82d3b290b12cd10ca49f0ff7608a6107\netty-nio-client-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.eclipse.angus\angus-activation\2.0.3\7f80607ea5014fef0b1779e6c33d63a88a45a563\angus-activation-2.0.3.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.glassfish.jaxb\txw2\4.0.6\4f4cd53b5ff9a2c5aa1211f15ed2569c57dfb044\txw2-4.0.6.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.sun.istack\istack-commons-runtime\4.1.2\18ec117c85f3ba0ac65409136afa8e42bc74e739\istack-commons-runtime-4.1.2.jar -Launcher Type: SUN_STANDARD - -[Global flags] - intx CICompilerCount = 12 {product} {ergonomic} - uint ConcGCThreads = 4 {product} {ergonomic} - uint G1ConcRefinementThreads = 14 {product} {ergonomic} - size_t G1HeapRegionSize = 4194304 {product} {ergonomic} - uintx GCDrainStackTargetSize = 64 {product} {ergonomic} - size_t InitialHeapSize = 532676608 {product} {ergonomic} - bool ManagementServer = true {product} {command line} - size_t MarkStackSize = 4194304 {product} {ergonomic} - size_t MaxHeapSize = 8480882688 {product} {ergonomic} - size_t MinHeapDeltaBytes = 4194304 {product} {ergonomic} - size_t MinHeapSize = 8388608 {product} {ergonomic} - uintx NonNMethodCodeHeapSize = 4096 {pd product} {ergonomic} - uintx NonProfiledCodeHeapSize = 0 {pd product} {ergonomic} - bool ProfileInterpreter = false {pd product} {command line} - uintx ProfiledCodeHeapSize = 0 {pd product} {ergonomic} - size_t SoftMaxHeapSize = 8480882688 {manageable} {ergonomic} - intx TieredStopAtLevel = 1 {product} {command line} - bool UseCompressedOops = true {product lp64_product} {ergonomic} - bool UseG1GC = true {product} {ergonomic} - bool UseLargePagesIndividualAllocation = false {pd product} {ergonomic} - -Logging: -Log output configuration: - #0: stdout all=warning uptime,level,tags foldmultilines=false - #1: stderr all=off uptime,level,tags foldmultilines=false - -Release file: - -Environment Variables: -JAVA_HOME=C:\Users\guswn\.jdks\corretto-19.0.2 -CLASSPATH=%JAVA_HOME%\lib -PATH=%JAVA_HOME%\bin;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\WINDOWS\System32\WindowsPowerShell\v1.0\;C:\WINDOWS\System32\OpenSSH\;D:\application\Git\cmd;C:\Program Files\Docker\Docker\resources\bin;D:\application\putty\;C:\Program Files\dotnet\;C:\Program Files\Bandizip\;D:\application\nodejs\;C:\Users\guswn\AppData\Local\Programs\Python\Python312\Scripts\;C:\Users\guswn\AppData\Local\Programs\Python\Python312\;C:\Users\guswn\AppData\Local\Programs\Python\Launcher\;C:\Users\guswn\AppData\Local\Microsoft\WindowsApps;D:\application\Microsoft VS Code\bin;C:\Users\guswn\AppData\Local\JetBrains\Toolbox\scripts;C:\Users\guswn\.local\bin;D:\application\IntelliJ IDEA 2025.3.2\bin;D:\application\JetBrains Gateway 2025.3.2\bin;C:\Users\guswn\AppData\Roaming\npm -USERNAME=guswn -OS=Windows_NT -PROCESSOR_IDENTIFIER=Intel64 Family 6 Model 170 Stepping 4, GenuineIntel -TMP=C:\Users\guswn\AppData\Local\Temp -TEMP=C:\Users\guswn\AppData\Local\Temp - - - - -Periodic native trim disabled - ---------------- S Y S T E M --------------- - -OS: - Windows 11 , 64 bit Build 26100 (10.0.26100.7920) -OS uptime: 16 days 18:33 hours -Hyper-V role detected - -CPU: total 18 (initial active 18) (9 cores per cpu, 2 threads per core) family 6 model 170 stepping 4 microcode 0x1f, cx8, cmov, fxsr, ht, mmx, 3dnowpref, sse, sse2, sse3, ssse3, sse4.1, sse4.2, popcnt, lzcnt, tsc, tscinvbit, avx, avx2, aes, erms, clmul, bmi1, bmi2, adx, sha, fma, vzeroupper, clflush, clflushopt, clwb, hv, serialize, rdtscp, rdpid, fsrm, f16c, cet_ibt, cet_ss -Processor Information for processor 0 - Max Mhz: 1200, Current Mhz: 1200, Mhz Limit: 1200 -Processor Information for processor 1 - Max Mhz: 1200, Current Mhz: 1200, Mhz Limit: 1200 -Processor Information for processor 2 - Max Mhz: 3600, Current Mhz: 700, Mhz Limit: 684 -Processor Information for processor 3 - Max Mhz: 3600, Current Mhz: 700, Mhz Limit: 684 -Processor Information for processor 4 - Max Mhz: 3600, Current Mhz: 700, Mhz Limit: 684 -Processor Information for processor 5 - Max Mhz: 3600, Current Mhz: 700, Mhz Limit: 684 -Processor Information for processor 6 - Max Mhz: 3600, Current Mhz: 700, Mhz Limit: 684 -Processor Information for processor 7 - Max Mhz: 3600, Current Mhz: 700, Mhz Limit: 684 -Processor Information for processor 8 - Max Mhz: 3600, Current Mhz: 700, Mhz Limit: 684 -Processor Information for processor 9 - Max Mhz: 3600, Current Mhz: 700, Mhz Limit: 684 -Processor Information for processor 10 - Max Mhz: 1200, Current Mhz: 1200, Mhz Limit: 1200 -Processor Information for processor 11 - Max Mhz: 1200, Current Mhz: 1200, Mhz Limit: 1200 -Processor Information for processor 12 - Max Mhz: 1200, Current Mhz: 1200, Mhz Limit: 1200 -Processor Information for processor 13 - Max Mhz: 1200, Current Mhz: 1200, Mhz Limit: 1200 -Processor Information for processor 14 - Max Mhz: 1200, Current Mhz: 1200, Mhz Limit: 1200 -Processor Information for processor 15 - Max Mhz: 1200, Current Mhz: 1200, Mhz Limit: 1200 -Processor Information for processor 16 - Max Mhz: 2500, Current Mhz: 700, Mhz Limit: 700 -Processor Information for processor 17 - Max Mhz: 2500, Current Mhz: 700, Mhz Limit: 700 - -Memory: 4k page, system-wide physical 32346M (3876M free) -TotalPageFile size 61970M (AvailPageFile size 336M) -current process WorkingSet (physical memory assigned to process): 13M, peak: 13M -current process commit charge ("private bytes"): 68M, peak: 576M - -vm_info: OpenJDK 64-Bit Server VM (21.0.10+7-LTS) for windows-amd64 JRE (21.0.10+7-LTS), built on 2026-01-15T22:13:46Z by "Administrator" with MS VC++ 17.14 (VS2022) - -END. diff --git a/hs_err_pid189152.log b/hs_err_pid189152.log deleted file mode 100644 index 12c25b95..00000000 --- a/hs_err_pid189152.log +++ /dev/null @@ -1,281 +0,0 @@ -# -# There is insufficient memory for the Java Runtime Environment to continue. -# Native memory allocation (mmap) failed to map 532676608 bytes. Error detail: G1 virtual space -# Possible reasons: -# The system is out of physical RAM or swap space -# This process is running with CompressedOops enabled, and the Java Heap may be blocking the growth of the native heap -# Possible solutions: -# Reduce memory load on the system -# Increase physical memory or swap space -# Check if swap backing store is full -# Decrease Java heap size (-Xmx/-Xms) -# Decrease number of Java threads -# Decrease Java thread stack sizes (-Xss) -# Set larger code cache with -XX:ReservedCodeCacheSize= -# JVM is running with Zero Based Compressed Oops mode in which the Java heap is -# placed in the first 32GB address space. The Java Heap base address is the -# maximum limit for the native heap growth. Please use -XX:HeapBaseMinAddress -# to set the Java Heap base and to place the Java Heap above 32GB virtual address. -# This output file may be truncated or incomplete. -# -# Out of Memory Error (os_windows.cpp:3714), pid=189152, tid=195204 -# -# JRE version: (21.0.10+7) (build ) -# Java VM: OpenJDK 64-Bit Server VM (21.0.10+7-LTS, mixed mode, emulated-client, sharing, tiered, compressed oops, compressed class ptrs, g1 gc, windows-amd64) -# No core dump will be written. Minidumps are not enabled by default on client versions of Windows -# - ---------------- S U M M A R Y ------------ - -Command Line: -XX:TieredStopAtLevel=1 -Dspring.profiles.active=local -Dspring.output.ansi.enabled=always -Dcom.sun.management.jmxremote -Dspring.jmx.enabled=true -Dspring.liveBeansView.mbeanDomain -Dspring.application.admin.enabled=true -Dmanagement.endpoints.jmx.exposure.include=* -javaagent:C:\Users\guswn\AppData\Local\Programs\IntelliJ IDEA\lib\idea_rt.jar=55101 -Dfile.encoding=UTF-8 -Dsun.stdout.encoding=UTF-8 -Dsun.stderr.encoding=UTF-8 com.swyp.picke.PickeApplication - -Host: Intel(R) Core(TM) Ultra 5 125H, 18 cores, 31G, Windows 11 , 64 bit Build 26100 (10.0.26100.7920) -Time: Mon Mar 30 22:58:27 2026 elapsed time: 2.032925 seconds (0d 0h 0m 2s) - ---------------- T H R E A D --------------- - -Current thread (0x0000027bde915cc0): JavaThread "Unknown thread" [_thread_in_vm, id=195204, stack(0x00000086bb400000,0x00000086bb500000) (1024K)] - -Stack: [0x00000086bb400000,0x00000086bb500000] -Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code) -V [jvm.dll+0x6df2b9] -V [jvm.dll+0x8bbdeb] -V [jvm.dll+0x8be37a] -V [jvm.dll+0x8bea53] -V [jvm.dll+0x28a7a6] -V [jvm.dll+0x6dbc15] -V [jvm.dll+0x6cfbca] -V [jvm.dll+0x364f6e] -V [jvm.dll+0x36ce3b] -V [jvm.dll+0x3be8d9] -V [jvm.dll+0x3beb7b] -V [jvm.dll+0x339137] -V [jvm.dll+0x339c7b] -V [jvm.dll+0x88634e] -V [jvm.dll+0x3cb831] -V [jvm.dll+0x86f25c] -V [jvm.dll+0x45e901] -V [jvm.dll+0x460541] -C [jli.dll+0x52f0] -C [ucrtbase.dll+0x37b0] -C [KERNEL32.DLL+0x2e8d7] -C [ntdll.dll+0x8c48c] - - ---------------- P R O C E S S --------------- - -Threads class SMR info: -_java_thread_list=0x00007ffa227e2208, length=0, elements={ -} - -Java Threads: ( => current thread ) -Total: 0 - -Other Threads: - 0x0000027bf46a03f0 WorkerThread "GC Thread#0" [id=7472, stack(0x00000086bb500000,0x00000086bb600000) (1024K)] - 0x0000027bde990120 ConcurrentGCThread "G1 Main Marker" [id=163140, stack(0x00000086bb600000,0x00000086bb700000) (1024K)] - 0x0000027bde991760 WorkerThread "G1 Conc#0" [id=152476, stack(0x00000086bb700000,0x00000086bb800000) (1024K)] - -[error occurred during error reporting (printing all threads), id 0xc0000005, EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x00007ffa21edbbb7] -VM state: not at safepoint (not fully initialized) - -VM Mutex/Monitor currently owned by a thread: ([mutex/lock_event]) -[0x00007ffa228566b0] Heap_lock - owner thread: 0x0000027bde915cc0 - -Heap address: 0x0000000606800000, size: 8088 MB, Compressed Oops mode: Zero based, Oop shift amount: 3 - -CDS archive(s) mapped at: [0x0000000000000000-0x0000000000000000-0x0000000000000000), size 0, SharedBaseAddress: 0x0000000800000000, ArchiveRelocationMode: 1. -Narrow klass base: 0x0000000000000000, Narrow klass shift: 0, Narrow klass range: 0x0 - -GC Precious Log: - CardTable entry size: 512 - Card Set container configuration: InlinePtr #cards 4 size 8 Array Of Cards #cards 32 size 80 Howl #buckets 8 coarsen threshold 7372 Howl Bitmap #cards 1024 size 144 coarsen threshold 921 Card regions per heap region 1 cards per card region 8192 - -Heap: - garbage-first heap total 0K, used 0K [0x0000000606800000, 0x0000000800000000) - region size 4096K, 0 young (0K), 0 survivors (0K) - -[error occurred during error reporting (printing heap information), id 0xc0000005, EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x00007ffa222c9019] -GC Heap History (0 events): -No events - -Dll operation events (1 events): -Event: 0.005 Loaded shared library D:\application\.jdk\bin\java.dll - -Deoptimization events (0 events): -No events - -Classes loaded (0 events): -No events - -Classes unloaded (0 events): -No events - -Classes redefined (0 events): -No events - -Internal exceptions (0 events): -No events - -ZGC Phase Switch (0 events): -No events - -VM Operations (0 events): -No events - -Memory protections (0 events): -No events - -Nmethod flushes (0 events): -No events - -Events (0 events): -No events - - -Dynamic libraries: -0x00007ff7fbf60000 - 0x00007ff7fbf6e000 D:\application\.jdk\bin\java.exe -0x00007ffb03b00000 - 0x00007ffb03d67000 C:\WINDOWS\SYSTEM32\ntdll.dll -0x00007ffb02ce0000 - 0x00007ffb02da9000 C:\WINDOWS\System32\KERNEL32.DLL -0x00007ffb00fa0000 - 0x00007ffb01391000 C:\WINDOWS\System32\KERNELBASE.dll -0x00007ffb003e0000 - 0x00007ffb0052b000 C:\WINDOWS\System32\ucrtbase.dll -0x00007ffae63b0000 - 0x00007ffae63c8000 D:\application\.jdk\bin\jli.dll -0x00007ffb02db0000 - 0x00007ffb02f75000 C:\WINDOWS\System32\USER32.dll -0x00007ffb015c0000 - 0x00007ffb015e7000 C:\WINDOWS\System32\win32u.dll -0x00007ffb02780000 - 0x00007ffb027ab000 C:\WINDOWS\System32\GDI32.dll -0x00007ffae7290000 - 0x00007ffae7523000 C:\WINDOWS\WinSxS\amd64_microsoft.windows.common-controls_6595b64144ccf1df_6.0.26100.8037_none_3e092faae333b53b\COMCTL32.dll -0x00007ffb031a0000 - 0x00007ffb03249000 C:\WINDOWS\System32\msvcrt.dll -0x00007ffb01770000 - 0x00007ffb0189b000 C:\WINDOWS\System32\gdi32full.dll -0x00007ffaeab10000 - 0x00007ffaeab2e000 D:\application\.jdk\bin\VCRUNTIME140.dll -0x00007ffb005f0000 - 0x00007ffb00693000 C:\WINDOWS\System32\msvcp_win.dll -0x00007ffb03160000 - 0x00007ffb03191000 C:\WINDOWS\System32\IMM32.DLL -0x00007ffaecfa0000 - 0x00007ffaecfac000 D:\application\.jdk\bin\vcruntime140_1.dll -0x00007ffad39c0000 - 0x00007ffad3a49000 D:\application\.jdk\bin\msvcp140.dll -0x00007ffa21b90000 - 0x00007ffa22938000 D:\application\.jdk\bin\server\jvm.dll -0x00007ffb01d30000 - 0x00007ffb01deb000 C:\WINDOWS\System32\ADVAPI32.dll -0x00007ffb03250000 - 0x00007ffb032f7000 C:\WINDOWS\System32\sechost.dll -0x00007ffb024a0000 - 0x00007ffb025b8000 C:\WINDOWS\System32\RPCRT4.dll -0x00007ffb029a0000 - 0x00007ffb02a14000 C:\WINDOWS\System32\WS2_32.dll -0x00007ffb00240000 - 0x00007ffb0029e000 C:\WINDOWS\SYSTEM32\POWRPROF.dll -0x00007ffaec6c0000 - 0x00007ffaec6f5000 C:\WINDOWS\SYSTEM32\WINMM.dll -0x00007ffae7a30000 - 0x00007ffae7a3b000 C:\WINDOWS\SYSTEM32\VERSION.dll -0x00007ffb00220000 - 0x00007ffb00234000 C:\WINDOWS\SYSTEM32\UMPDC.dll -0x00007ffaff170000 - 0x00007ffaff18b000 C:\WINDOWS\SYSTEM32\kernel.appcore.dll -0x00007ffaea260000 - 0x00007ffaea26a000 D:\application\.jdk\bin\jimage.dll -0x00007ffafe4f0000 - 0x00007ffafe732000 C:\WINDOWS\SYSTEM32\DBGHELP.DLL -0x00007ffb01e50000 - 0x00007ffb021d2000 C:\WINDOWS\System32\combase.dll -0x00007ffb02f80000 - 0x00007ffb03057000 C:\WINDOWS\System32\OLEAUT32.dll -0x00007ffada3d0000 - 0x00007ffada40b000 C:\WINDOWS\SYSTEM32\dbgcore.DLL -0x00007ffb013a0000 - 0x00007ffb01445000 C:\WINDOWS\System32\bcryptPrimitives.dll -0x00007ffae63a0000 - 0x00007ffae63b0000 D:\application\.jdk\bin\instrument.dll -0x00007ffae6310000 - 0x00007ffae6331000 D:\application\.jdk\bin\java.dll - -JVMTI agents: -C:\Users\guswn\AppData\Local\Programs\IntelliJ IDEA\lib\idea_rt.jar path:none, loaded, not initialized, instrumentlib options:55101 - -dbghelp: loaded successfully - version: 4.0.5 - missing functions: none -symbol engine: initialized successfully - sym options: 0x614 - pdb path: .;D:\application\.jdk\bin;C:\WINDOWS\SYSTEM32;C:\WINDOWS\WinSxS\amd64_microsoft.windows.common-controls_6595b64144ccf1df_6.0.26100.8037_none_3e092faae333b53b;D:\application\.jdk\bin\server - -VM Arguments: -jvm_args: -XX:TieredStopAtLevel=1 -Dspring.profiles.active=local -Dspring.output.ansi.enabled=always -Dcom.sun.management.jmxremote -Dspring.jmx.enabled=true -Dspring.liveBeansView.mbeanDomain -Dspring.application.admin.enabled=true -Dmanagement.endpoints.jmx.exposure.include=* -javaagent:C:\Users\guswn\AppData\Local\Programs\IntelliJ IDEA\lib\idea_rt.jar=55101 -Dfile.encoding=UTF-8 -Dsun.stdout.encoding=UTF-8 -Dsun.stderr.encoding=UTF-8 -java_command: com.swyp.picke.PickeApplication -java_class_path (initial): D:\Desktop\project\Server\build\classes\java\main;D:\Desktop\project\Server\build\resources\main;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.projectlombok\lombok\1.18.42\8365263844ebb62398e0dc33057ba10ba472d3b8\lombok-1.18.42.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter-web\3.5.11\68fde4c94249e92526105a93ac7c22bd89b6945e\spring-boot-starter-web-3.5.11.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springdoc\springdoc-openapi-starter-webmvc-ui\2.8.16\61c68f705d3f17e8318fb18b2904fa6368af251c\springdoc-openapi-starter-webmvc-ui-2.8.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter-validation\3.5.11\903eefb6eab302617b0f01cc6d65664343bff2a7\spring-boot-starter-validation-3.5.11.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter-data-jpa\3.5.11\f176e5c643720818ec7910e1dd2ccb402411cc5d\spring-boot-starter-data-jpa-3.5.11.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter-security\3.5.11\db8b6b7951883dea3ce7404f20d6816104cedd4e\spring-boot-starter-security-3.5.11.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.jsonwebtoken\jjwt-api\0.12.6\478886a888f6add04937baf0361144504a024967\jjwt-api-0.12.6.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter-webflux\3.5.11\1461f9a6b6b8397ad71a98c9bbf4278159fb9624\spring-boot-starter-webflux-3.5.11.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.crypto.tink\apps-rewardedads\1.9.1\cbaf11457b36fe57d90a5cb16a76833906486503\apps-rewardedads-1.9.1.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.cloud\google-cloud-texttospeech\2.58.0\9be37bd3c81c14c72c9cbcfa2dfaf6dad7a35075\google-cloud-texttospeech-2.58.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.awspring.cloud\spring-cloud-aws-starter-s3\3.3.0\fa9790f990ab540814aafdbf2e97c8cd53b5b1a6\spring-cloud-aws-starter-s3-3.3.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter-thymeleaf\3.5.11\d997aa0df579cf43507d425057940e2712e44808\spring-boot-starter-thymeleaf-3.5.11.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter-json\3.5.11\4cdcd68dcddf0a4c645166e39c3fe448fe2b8e98\spring-boot-starter-json-3.5.11.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter\3.5.11\10ce971300fd56d6be5f1cfe7d27ddfb1ed7158d\spring-boot-starter-3.5.11.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter-tomcat\3.5.11\fb7b96cb61e5fd5700aed96194562e32d166b5ef\spring-boot-starter-tomcat-3.5.11.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework\spring-webmvc\6.2.16\ff2db80406f1459fddd14a8d06d57e0e3ab69465\spring-webmvc-6.2.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework\spring-web\6.2.16\2c4355f1f7e5b8969f696cbc90f25cc22f0f2164\spring-web-6.2.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springdoc\springdoc-openapi-starter-webmvc-api\2.8.16\6e41988d84978e529c01a4cc052b761cd27d5b90\springdoc-openapi-starter-webmvc-api-2.8.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.webjars\swagger-ui\5.32.0\d04c7e3e5b8616813136fa36382a548751775528\swagger-ui-5.32.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.webjars\webjars-locator-lite\1.1.3\217ce590453251b39b72c4a9af3986998f6fdbd9\webjars-locator-lite-1.1.3.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.apache.tomcat.embed\tomcat-embed-el\10.1.52\cd94ce17c5a9937eca365eb494711efa10d49b86\tomcat-embed-el-10.1.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.hibernate.validator\hibernate-validator\8.0.3.Final\4425f554297a1c5ba03a3f30e559a9fd91048cf8\hibernate-validator-8.0.3.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter-jdbc\3.5.11\3ce801963caadf6eb29abd68f5a0fe50c9bfe211\spring-boot-starter-jdbc-3.5.11.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.hibernate.orm\hibernate-core\6.6.42.Final\996e3df4a6c67941b582e4493cb9a39c83198f1e\hibernate-core-6.6.42.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.data\spring-data-jpa\3.5.9\56081dde4f663db74ba000c1f8ab30673058c363\spring-data-jpa-3.5.9.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework\spring-aspects\6.2.16\763140a66821c494985533f29280a3b4132cf055\spring-aspects-6.2.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.security\spring-security-web\6.5.8\3db7bf41191d5b23493cca6252595405b5112b34\spring-security-web-6.5.8.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.security\spring-security-config\6.5.8\302d32eba89131c0ffd15ba0a1e465051336d42f\spring-security-config-6.5.8.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework\spring-aop\6.2.16\59250efa248420a114fe23b4ccf2fea46b804186\spring-aop-6.2.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework\spring-webflux\6.2.16\699ef8bc182893f9ed43206d372f20c4f9aa3231\spring-webflux-6.2.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter-reactor-netty\3.5.11\f98bd3e3019078679dec4f21fb63152aa2e059a7\spring-boot-starter-reactor-netty-3.5.11.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.crypto.tink\tink\1.10.0\84771b1a4bb5726f73fb8490fadb23f1d2aacd38\tink-1.10.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.code.gson\gson\2.13.2\48b8230771e573b54ce6e867a9001e75977fe78e\gson-2.13.2.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.http-client\google-http-client\1.45.3\dde98b597081b98514867c9cefa551fcdea3a28c\google-http-client-1.45.3.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.errorprone\error_prone_annotations\2.41.0\4381275efdef6ddfae38f002c31e84cd001c97f0\error_prone_annotations-2.41.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.opencensus\opencensus-contrib-http-util\0.31.1\3c13fc5715231fadb16a9b74a44d9d59c460cfa8\opencensus-contrib-http-util-0.31.1.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.guava\guava\33.4.0-jre\3fcc0a259f724c7de54a6a55ea7e26d3d5c0cac\guava-33.4.0-jre.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.grpc\grpc-api\1.69.0\965c2c7f708cd6e6ddbf1eb175c3e87e96e41297\grpc-api-1.69.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.code.findbugs\jsr305\3.0.2\25ea2e8b0c338a877313bd4672d3fe056ea78f0d\jsr305-3.0.2.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.grpc\grpc-stub\1.69.0\9e7dc30a9c2df70e25ef4b941f46187e6e178e7a\grpc-stub-1.69.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.grpc\grpc-protobuf\1.69.0\2990b4948357d4fe46aaecb47290cff102079f1e\grpc-protobuf-1.69.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.api\api-common\2.43.0\963d97d95e9bf7275cc26f0b6b72e2aa5b92c6fd\api-common-2.43.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.auto.value\auto-value-annotations\1.11.0\f0d047931d07cfbc6fa4079854f181ff62891d6f\auto-value-annotations-1.11.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\javax.annotation\javax.annotation-api\1.3.2\934c04d3cfef185a8008e7bf34331b79730a9d43\javax.annotation-api-1.3.2.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.j2objc\j2objc-annotations\3.0.0\7399e65dd7e9ff3404f4535b2f017093bdb134c7\j2objc-annotations-3.0.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.protobuf\protobuf-java\3.25.5\5ae5c9ec39930ae9b5a61b32b93288818ec05ec1\protobuf-java-3.25.5.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.api.grpc\proto-google-common-protos\2.51.0\ead75a32e6fd65740b6a69feb658254aeab3fef0\proto-google-common-protos-2.51.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.api.grpc\proto-google-cloud-texttospeech-v1\2.58.0\42f1f29876ddfa2523ebcc41dae801195fd8b3ce\proto-google-cloud-texttospeech-v1-2.58.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.api.grpc\proto-google-cloud-texttospeech-v1beta1\0.147.0\576df432a2c1181deabf21a54fdecc1a32f69f4e\proto-google-cloud-texttospeech-v1beta1-0.147.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.guava\failureaccess\1.0.2\c4a06a64e650562f30b7bf9aaec1bfed43aca12b\failureaccess-1.0.2.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.guava\listenablefuture\9999.0-empty-to-avoid-conflict-with-guava\b421526c5f297295adef1c886e5246c39d4ac629\listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.checkerframework\checker-qual\3.48.4\6b5d69a61012211d581e68699baf3beb1fd382da\checker-qual-3.48.4.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.api\gax\2.60.0\2d277e0795cb69bc14e03be068aa002539e3ef49\gax-2.60.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.auth\google-auth-library-credentials\1.31.0\b9cd5346d3a683d9a8d9786453f2419cc832a97f\google-auth-library-credentials-1.31.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.opencensus\opencensus-api\0.31.1\66a60c7201c2b8b20ce495f0295b32bb0ccbbc57\opencensus-api-0.31.1.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.grpc\grpc-context\1.69.0\cea23878872f76418dcd6df0c6eef0bf27463537\grpc-context-1.69.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.auth\google-auth-library-oauth2-http\1.31.0\df5be46d21b983aab8d0250f19b585a94bdedcde\google-auth-library-oauth2-http-1.31.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.api\gax-grpc\2.60.0\ca4d7dc8c2a85fbdba25ff3449726852e2359ae9\gax-grpc-2.60.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.grpc\grpc-inprocess\1.69.0\8ac4d2e13b48bed9624b8bc485c90f3d28820c93\grpc-inprocess-1.69.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.grpc\grpc-core\1.69.0\7dad3419dfb91a77788afcdf79e0477172784910\grpc-core-1.69.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.grpc\grpc-alts\1.69.0\6d1eac6726fd6fd177666c10fd154823b82272eb\grpc-alts-1.69.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.grpc\grpc-grpclb\1.69.0\d2c9c066693ce94805a503bc47f5b1e76f51541c\grpc-grpclb-1.69.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.conscrypt\conscrypt-openjdk-uber\2.5.2\d858f142ea189c62771c505a6548d8606ac098fe\conscrypt-openjdk-uber-2.5.2.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.grpc\grpc-auth\1.69.0\a75e19b20bb732364bdcc0979e9d7c9baa4e408e\grpc-auth-1.69.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.grpc\grpc-netty-shaded\1.69.0\99aa9789172695a4b09fe2af5f5bd0ab1be4ae85\grpc-netty-shaded-1.69.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.api\gax-httpjson\2.60.0\131d9283925337406e35561ec17bf326a9ecec1a\gax-httpjson-2.60.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.apache.httpcomponents\httpclient\4.5.14\1194890e6f56ec29177673f2f12d0b8e627dec98\httpclient-4.5.14.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\commons-codec\commons-codec\1.18.0\ee45d1cf6ec2cc2b809ff04b4dc7aec858e0df8f\commons-codec-1.18.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.apache.httpcomponents\httpcore\4.4.16\51cf043c87253c9f58b539c9f7e44c8894223850\httpcore-4.4.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.http-client\google-http-client-gson\1.45.3\29eba40245c4a4e5466f8764bd894d6a97c6694f\google-http-client-gson-1.45.3.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.protobuf\protobuf-java-util\3.25.5\38cc5ce479603e36466feda2a9f1dfdb2210ef00\protobuf-java-util-3.25.5.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.threeten\threetenbp\1.7.0\8703e893440e550295aa358281db468625bc9a05\threetenbp-1.7.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.awspring.cloud\spring-cloud-aws-starter\3.3.0\7d82d320cb1851beca3005eab2e484a38bd58a08\spring-cloud-aws-starter-3.3.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.awspring.cloud\spring-cloud-aws-s3\3.3.0\661e2914e3ad6555e20ffa262a9987c15bcc1712\spring-cloud-aws-s3-3.3.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.slf4j\slf4j-api\2.0.17\d9e58ac9c7779ba3bf8142aff6c830617a7fe60f\slf4j-api-2.0.17.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.thymeleaf\thymeleaf-spring6\3.1.3.RELEASE\4b276ea2bd536a18e44b40ff1d9f4848965ff59c\thymeleaf-spring6-3.1.3.RELEASE.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.fasterxml.jackson.datatype\jackson-datatype-jdk8\2.19.4\90d304bcdb1a4bacb6f4347be625d75300973c60\jackson-datatype-jdk8-2.19.4.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.fasterxml.jackson.datatype\jackson-datatype-jsr310\2.19.4\3cbcf2e636a6b062772299bf19a347536e58c4df\jackson-datatype-jsr310-2.19.4.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.fasterxml.jackson.module\jackson-module-parameter-names\2.19.4\502dfea4c83502f444837b3d040a51e8475f15f2\jackson-module-parameter-names-2.19.4.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.fasterxml.jackson.core\jackson-databind\2.19.4\7a39bf9257b726b90b80f27fa3f5174bc75162a5\jackson-databind-2.19.4.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-autoconfigure\3.5.11\3c7d2ec2ac3c301e95814e37fed1c86c19927fc4\spring-boot-autoconfigure-3.5.11.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot\3.5.11\8b7f6df00bfbe74d370e1d05d985a127884d2a9c\spring-boot-3.5.11.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter-logging\3.5.11\62b692ed7aee31a5670796be8b07732b6b836f4e\spring-boot-starter-logging-3.5.11.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\jakarta.annotation\jakarta.annotation-api\2.1.1\48b9bda22b091b1f48b13af03fe36db3be6e1ae3\jakarta.annotation-api-2.1.1.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework\spring-core\6.2.16\a73937f20a303e057add523915b48eb7901e1848\spring-core-6.2.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.yaml\snakeyaml\2.4\e0666b825b796f85521f02360e77f4c92c5a7a07\snakeyaml-2.4.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.apache.tomcat.embed\tomcat-embed-websocket\10.1.52\9d32b801fb474306349013fcdd8317c8cb4d739e\tomcat-embed-websocket-10.1.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.apache.tomcat.embed\tomcat-embed-core\10.1.52\f512bef2796b51299f4752f95918982c3003131d\tomcat-embed-core-10.1.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework\spring-context\6.2.16\caeae6bd50832d6ab28f707aa740e957401a5c20\spring-context-6.2.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework\spring-beans\6.2.16\990289064c810be71630fca9da8e2b6fe8f897b5\spring-beans-6.2.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework\spring-expression\6.2.16\e293ab797b1698084e56ae1f2362b315148683f6\spring-expression-6.2.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.micrometer\micrometer-observation\1.15.9\edf37b25cdfac0704d6fefa4543edb3ed1817eb0\micrometer-observation-1.15.9.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springdoc\springdoc-openapi-starter-common\2.8.16\5b702cb484981b42cfb455bd80b6ce7f49d34210\springdoc-openapi-starter-common-2.8.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.jspecify\jspecify\1.0.0\7425a601c1c7ec76645a78d22b8c6a627edee507\jspecify-1.0.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\jakarta.validation\jakarta.validation-api\3.0.2\92b6631659ba35ca09e44874d3eb936edfeee532\jakarta.validation-api-3.0.2.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.jboss.logging\jboss-logging\3.6.2.Final\3e0a139d7a74cc13b5e01daa8aaa7f71dccd577e\jboss-logging-3.6.2.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.fasterxml\classmate\1.7.3\f61c7e7b81e9249b0f6a05914eff9d54fb09f4a0\classmate-1.7.3.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.zaxxer\HikariCP\6.3.3\7c5aec1e47a97ff40977e0193018865304ea9585\HikariCP-6.3.3.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework\spring-jdbc\6.2.16\addfdde7b3212f34c95d791c37bb04ba4b08a1b7\spring-jdbc-6.2.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\jakarta.persistence\jakarta.persistence-api\3.1.0\66901fa1c373c6aff65c13791cc11da72060a8d6\jakarta.persistence-api-3.1.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\jakarta.transaction\jakarta.transaction-api\2.0.1\51a520e3fae406abb84e2e1148e6746ce3f80a1a\jakarta.transaction-api-2.0.1.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.data\spring-data-commons\3.5.9\6b577c71f563e78a7da984a3d572fde8a4df8103\spring-data-commons-3.5.9.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework\spring-orm\6.2.16\44b3cfb2c046440f83729641c929c405dc7f2c89\spring-orm-6.2.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework\spring-tx\6.2.16\5f9d6e78b76530e6258de8a0dff991fb1ad4b9b0\spring-tx-6.2.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.antlr\antlr4-runtime\4.13.0\5a02e48521624faaf5ff4d99afc88b01686af655\antlr4-runtime-4.13.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.aspectj\aspectjweaver\1.9.25.1\a713c790da4d794c7dfb542b550d4e44898d5e23\aspectjweaver-1.9.25.1.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.security\spring-security-core\6.5.8\d052dca52e49d95d2b03f81ae4b6762eeb4c78d0\spring-security-core-6.5.8.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.projectreactor\reactor-core\3.7.16\dc7f2ba3c4fbc69678937dfe1ad45264d8a1c7be\reactor-core-3.7.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.projectreactor.netty\reactor-netty-http\1.2.15\b20bb13c95b44f1d0c148bdf1197b7d4a7e0f278\reactor-netty-http-1.2.15.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.awspring.cloud\spring-cloud-aws-autoconfigure\3.3.0\b5a0b27e91ee997f8c86e4b0c521858fdcb9dc9b\spring-cloud-aws-autoconfigure-3.3.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.awspring.cloud\spring-cloud-aws-core\3.3.0\3c501426267d8ccbaaebc9796bd5de5bc5d0702e\spring-cloud-aws-core-3.3.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\s3\2.29.52\db65bc6177b0c4514be1f9775cb2094e29e85d3c\s3-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.thymeleaf\thymeleaf\3.1.3.RELEASE\51474f2a90b282ee97dabcd159c7faf24790f373\thymeleaf-3.1.3.RELEASE.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.fasterxml.jackson.core\jackson-core\2.19.4\a720ca9b800742699e041c3890f3731fe516085e\jackson-core-2.19.4.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.fasterxml.jackson.core\jackson-annotations\2.19.4\bbb09b1e7f7f5108890270eb701cb3ddef991c05\jackson-annotations-2.19.4.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\ch.qos.logback\logback-classic\1.5.32\2b1042c50f508f2eb402bd4d22ccbdf94cc37d2e\logback-classic-1.5.32.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.apache.logging.log4j\log4j-to-slf4j\2.24.3\da1143e2a2531ee1c2d90baa98eb50a28a39d5a7\log4j-to-slf4j-2.24.3.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.slf4j\jul-to-slf4j\2.0.17\524cb6ccc2b68a57604750e1ab8b13b5a786a6aa\jul-to-slf4j-2.0.17.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework\spring-jcl\6.2.16\8af6546d28815be574f384dceb93d248e9934f90\spring-jcl-6.2.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.micrometer\micrometer-commons\1.15.9\5a38f43cdc79a309a458c8ce130fff30a2a7f59\micrometer-commons-1.15.9.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.swagger.core.v3\swagger-core-jakarta\2.2.43\500566364be54e3556bcec28922a41ca5fcc7dcd\swagger-core-jakarta-2.2.43.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.security\spring-security-crypto\6.5.8\aec1a6f6c0e06be9dff08b11e8e1f457afca44b2\spring-security-crypto-6.5.8.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.reactivestreams\reactive-streams\1.0.4\3864a1320d97d7b045f729a326e1e077661f31b7\reactive-streams-1.0.4.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.projectreactor.netty\reactor-netty-core\1.2.15\94b2ca82f310c1bf31d3038060e4572eeca1d4b2\reactor-netty-core-1.2.15.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-codec-http2\4.1.131.Final\2e4c47131c60e0bbbca067c891597b466f7033ba\netty-codec-http2-4.1.131.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-codec-http\4.1.131.Final\253d80637ed689ed309ca62371e5fb97746b165\netty-codec-http-4.1.131.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-resolver-dns-native-macos\4.1.131.Final\9e4a908c073e56caa4127f54d946e3e9a5208506\netty-resolver-dns-native-macos-4.1.131.Final-osx-x86_64.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-resolver-dns\4.1.131.Final\7714c0babe26712ccfdbc158aa64898ab909e7d8\netty-resolver-dns-4.1.131.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-transport-native-epoll\4.1.131.Final\10b7a905019c1ad5c37e8cf63d7229fb00668c1d\netty-transport-native-epoll-4.1.131.Final-linux-x86_64.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\aws-core\2.29.52\dcfa86ac727b5d4e0abad1e8b025ac2febb6382e\aws-core-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\auth\2.29.52\76f9b22a99b0de0fd31447db22a5cba4ed4b172e\auth-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\regions\2.29.52\270b31c8695739d495452d380d036c72698e623\regions-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\aws-xml-protocol\2.29.52\e7290d4528affec022bd2f3739853f774a955ac2\aws-xml-protocol-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\protocol-core\2.29.52\1a0e4a114c0943142ca395000a949ee840890fea\protocol-core-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\sdk-core\2.29.52\3f058b489fac3d091417339e02b165e72c637f61\sdk-core-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\arns\2.29.52\879712423589b58434b8831b9b75304a16983178\arns-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\profiles\2.29.52\59dd1368bff2d242d84515ec7ea8fe63bb472c4e\profiles-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\crt-core\2.29.52\6a16e04be0e8bb8a1767e0644c631dadddfdd764\crt-core-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\http-auth\2.29.52\aa4ce3ff7bcd8dcf131a4f5445455b3eb4926dcf\http-auth-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\http-auth-aws\2.29.52\1d0dbfa072bc46207066ffa498ad4ed65c52ac6d\http-auth-aws-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\http-auth-spi\2.29.52\4a64e68a88e3eef0b51819f742931f3607cdd996\http-auth-spi-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\identity-spi\2.29.52\d18449651e8798398cadab6c4b5d8594bb0281c\identity-spi-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\checksums\2.29.52\90631313060ff8ef1ab7745bb1e9740913bdcefc\checksums-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\retries-spi\2.29.52\7e2c7ad44106799491de8cced5925b6473d62e4b\retries-spi-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\http-client-spi\2.29.52\a8da4f289736c702ec6664836761412e7e1e54a2\http-client-spi-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\metrics-spi\2.29.52\92c3797208d24b2b25ab9b6d1bbab624c3af1b9c\metrics-spi-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\json-utils\2.29.52\d88c6c03061b9f3fcd17dc8456365dab67cc1597\json-utils-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\utils\2.29.52\bde94a15cd79b0240bfa10230970e2f0e4c51eba\utils-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\checksums-spi\2.29.52\537363296f035a935b7d3b50a5bef90014d38010\checksums-spi-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\endpoints-spi\2.29.52\bd702a44ad440628af93afa1ec1d7cdc56baec67\endpoints-spi-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\annotations\2.29.52\9fa958ce528b57d90db01c5015daaf7bd373e57f\annotations-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.attoparser\attoparser\2.0.7.RELEASE\e5d0e988d9124139d645bb5872b24dfa23e283cc\attoparser-2.0.7.RELEASE.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.unbescape\unbescape\1.1.6.RELEASE\7b90360afb2b860e09e8347112800d12c12b2a13\unbescape-1.1.6.RELEASE.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\ch.qos.logback\logback-core\1.5.32\fdfb3ff9a842303d4a95207294a6c6bc64e2605d\logback-core-1.5.32.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.apache.logging.log4j\log4j-api\2.24.3\b02c125db8b6d295adf72ae6e71af5d83bce2370\log4j-api-2.24.3.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.swagger.core.v3\swagger-models-jakarta\2.2.43\a68f7470eb763609878460272000f260eabc24dc\swagger-models-jakarta-2.2.43.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.fasterxml.jackson.dataformat\jackson-dataformat-yaml\2.19.4\500956daea0869bf753b94fdaa77e5dc99847d79\jackson-dataformat-yaml-2.19.4.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.apache.commons\commons-lang3\3.17.0\b17d2136f0460dcc0d2016ceefca8723bdf4ee70\commons-lang3-3.17.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.swagger.core.v3\swagger-annotations-jakarta\2.2.43\dbd40253251deabb7a628a54b4550dc4fb492f4\swagger-annotations-jakarta-2.2.43.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\jakarta.xml.bind\jakarta.xml.bind-api\4.0.4\d6d2327f3817d9a33a3b6b8f2e15a96bc2e7afdc\jakarta.xml.bind-api-4.0.4.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-handler-proxy\4.1.131.Final\5ff9e74613a9dd3ca078f06880a16c8cdc046de0\netty-handler-proxy-4.1.131.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-handler\4.1.131.Final\5ca67999f41c0a68f0b66485ceb990683a0b0694\netty-handler-4.1.131.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-codec\4.1.131.Final\1874341f7b29879c6833c17e7305272f0cdc2cb6\netty-codec-4.1.131.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-transport\4.1.131.Final\474862e0855d7a9828fab06a9c73c05387604ee3\netty-transport-4.1.131.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-buffer\4.1.131.Final\f97b636ecd9b81ae3fd1d039b69c4fd3959ecf\netty-buffer-4.1.131.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-common\4.1.131.Final\cdc659109da226b698a74b543a5b97dd0f7e6959\netty-common-4.1.131.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-resolver-dns-classes-macos\4.1.131.Final\b9d57038cc4144e36aee5898085b7f1f018d2c9f\netty-resolver-dns-classes-macos-4.1.131.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-codec-dns\4.1.131.Final\cd23e12e5c3448a1b12c8a4b8deeb4faeb5e483e\netty-codec-dns-4.1.131.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-resolver\4.1.131.Final\9db1bfd7c57b9b6aa9b5cfc61fc3304594bb6b39\netty-resolver-4.1.131.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-transport-classes-epoll\4.1.131.Final\4d7848ac709491fb14f8bce2796fc3eff4a04fd6\netty-transport-classes-epoll-4.1.131.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-transport-native-unix-common\4.1.131.Final\fa975e4751b23d50c0a60569829f31944d11d292\netty-transport-native-unix-common-4.1.131.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\retries\2.29.52\48cb57817dd88977ec71e63550673c5ce010a191\retries-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.eventstream\eventstream\1.0.1\6ff8649dffc5190366ada897ba8525a836297784\eventstream-1.0.1.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\http-auth-aws-eventstream\2.29.52\e8b723c48008bcac96e2cc34c7415bd8b581c601\http-auth-aws-eventstream-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\aws-query-protocol\2.29.52\672d7a2df481414d02eedf3a9eff45fb87f1b8a\aws-query-protocol-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\third-party-jackson-core\2.29.52\82ff600d837e83130502775a1555c45d7a3e2e1\third-party-jackson-core-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\jakarta.activation\jakarta.activation-api\2.1.4\9e5c2a0d75dde71a0bedc4dbdbe47b78a5dc50f8\jakarta.activation-api-2.1.4.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-codec-socks\4.1.131.Final\614eacc17f44d8abaeaea81f210b4980c3568262\netty-codec-socks-4.1.131.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-devtools\3.5.11\fe7dfcaf3153d049909a618a7ba7df288e80f090\spring-boot-devtools-3.5.11.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.jsonwebtoken\jjwt-impl\0.12.6\ac23673a84b6089e0369fb8ab2c69edd91cd6eb0\jjwt-impl-0.12.6.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.jsonwebtoken\jjwt-jackson\0.12.6\f141e0c1136ba17f2632858238a31ae05642dbf8\jjwt-jackson-0.12.6.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.postgresql\postgresql\42.7.10\35100a3f0899551e27af8fed4a3414619a4663b3\postgresql-42.7.10.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.h2database\h2\2.3.232\4fcc05d966ccdb2812ae8b9a718f69226c0cf4e2\h2-2.3.232.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.grpc\grpc-protobuf-lite\1.69.0\91711f27421babf868e424a64426fccb9e8bf6ec\grpc-protobuf-lite-1.69.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.checkerframework\checker-qual\3.52.0\9c17f496846ab1fca8975c6a50ceac0b3bbe63f0\checker-qual-3.52.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.android\annotations\4.1.1.4\a1678ba907bf92691d879fef34e1a187038f9259\annotations-4.1.1.4.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.codehaus.mojo\animal-sniffer-annotations\1.24\aa9ba58d30e0aad7f1808fce9c541ea3760678d8\animal-sniffer-annotations-1.24.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.grpc\grpc-util\1.69.0\1929ab12fce0c610d9d7229b8767f6abb09ebd51\grpc-util-1.69.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.perfmark\perfmark-api\0.27.0\f86f575a41b091786a4b027cd9c0c1d2e3fc1c01\perfmark-api-0.27.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.grpc\grpc-googleapis\1.69.0\1c11a033d96689a4bf3c92fe89b35f5edaef10c2\grpc-googleapis-1.69.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.grpc\grpc-xds\1.69.0\fa1d282a8ba3ae2a5dc0205d2f6a18b5606b5b62\grpc-xds-1.69.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.grpc\grpc-services\1.69.0\bcd917dad2380ee7cf4728da33816ffb9fad6b8b\grpc-services-1.69.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.re2j\re2j\1.7\2949632c1b4acce0d7784f28e3152e9cf3c2ec7a\re2j-1.7.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.hibernate.common\hibernate-commons-annotations\7.0.3.Final\e183c4be8bb41d12e9f19b374e00c34a0a85f439\hibernate-commons-annotations-7.0.3.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.smallrye\jandex\3.2.0\f17ad860f62a08487b9edabde608f8ac55c62fa7\jandex-3.2.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\net.bytebuddy\byte-buddy\1.17.8\af5735f63d00ca47a9375fae5c7471a36331c6ed\byte-buddy-1.17.8.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.glassfish.jaxb\jaxb-runtime\4.0.6\fb95ebb62564657b2fedfe165b859789ef3a8711\jaxb-runtime-4.0.6.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\jakarta.inject\jakarta.inject-api\2.0.1\4c28afe1991a941d7702fe1362c365f0a8641d1e\jakarta.inject-api-2.0.1.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.glassfish.jaxb\jaxb-core\4.0.6\8e61282303777fc98a00cc3affd0560d68748a75\jaxb-core-4.0.6.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\apache-client\2.29.52\b7ce213c946d69ab1807b3f7ecac1ce29ed60485\apache-client-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\netty-nio-client\2.29.52\20fa79ba82d3b290b12cd10ca49f0ff7608a6107\netty-nio-client-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.eclipse.angus\angus-activation\2.0.3\7f80607ea5014fef0b1779e6c33d63a88a45a563\angus-activation-2.0.3.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.glassfish.jaxb\txw2\4.0.6\4f4cd53b5ff9a2c5aa1211f15ed2569c57dfb044\txw2-4.0.6.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.sun.istack\istack-commons-runtime\4.1.2\18ec117c85f3ba0ac65409136afa8e42bc74e739\istack-commons-runtime-4.1.2.jar -Launcher Type: SUN_STANDARD - -[Global flags] - intx CICompilerCount = 12 {product} {ergonomic} - uint ConcGCThreads = 4 {product} {ergonomic} - uint G1ConcRefinementThreads = 14 {product} {ergonomic} - size_t G1HeapRegionSize = 4194304 {product} {ergonomic} - uintx GCDrainStackTargetSize = 64 {product} {ergonomic} - size_t InitialHeapSize = 532676608 {product} {ergonomic} - bool ManagementServer = true {product} {command line} - size_t MarkStackSize = 4194304 {product} {ergonomic} - size_t MaxHeapSize = 8480882688 {product} {ergonomic} - size_t MinHeapDeltaBytes = 4194304 {product} {ergonomic} - size_t MinHeapSize = 8388608 {product} {ergonomic} - uintx NonNMethodCodeHeapSize = 4096 {pd product} {ergonomic} - uintx NonProfiledCodeHeapSize = 0 {pd product} {ergonomic} - bool ProfileInterpreter = false {pd product} {command line} - uintx ProfiledCodeHeapSize = 0 {pd product} {ergonomic} - size_t SoftMaxHeapSize = 8480882688 {manageable} {ergonomic} - intx TieredStopAtLevel = 1 {product} {command line} - bool UseCompressedOops = true {product lp64_product} {ergonomic} - bool UseG1GC = true {product} {ergonomic} - bool UseLargePagesIndividualAllocation = false {pd product} {ergonomic} - -Logging: -Log output configuration: - #0: stdout all=warning uptime,level,tags foldmultilines=false - #1: stderr all=off uptime,level,tags foldmultilines=false - -Release file: - -Environment Variables: -JAVA_HOME=C:\Users\guswn\.jdks\corretto-19.0.2 -CLASSPATH=%JAVA_HOME%\lib -PATH=%JAVA_HOME%\bin;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\WINDOWS\System32\WindowsPowerShell\v1.0\;C:\WINDOWS\System32\OpenSSH\;D:\application\Git\cmd;C:\Program Files\Docker\Docker\resources\bin;D:\application\putty\;C:\Program Files\dotnet\;C:\Program Files\Bandizip\;D:\application\nodejs\;C:\Users\guswn\AppData\Local\Programs\Python\Python312\Scripts\;C:\Users\guswn\AppData\Local\Programs\Python\Python312\;C:\Users\guswn\AppData\Local\Programs\Python\Launcher\;C:\Users\guswn\AppData\Local\Microsoft\WindowsApps;D:\application\Microsoft VS Code\bin;C:\Users\guswn\AppData\Local\JetBrains\Toolbox\scripts;C:\Users\guswn\.local\bin;D:\application\IntelliJ IDEA 2025.3.2\bin;D:\application\JetBrains Gateway 2025.3.2\bin;C:\Users\guswn\AppData\Roaming\npm -USERNAME=guswn -OS=Windows_NT -PROCESSOR_IDENTIFIER=Intel64 Family 6 Model 170 Stepping 4, GenuineIntel -TMP=C:\Users\guswn\AppData\Local\Temp -TEMP=C:\Users\guswn\AppData\Local\Temp - - - - -Periodic native trim disabled - ---------------- S Y S T E M --------------- - -OS: - Windows 11 , 64 bit Build 26100 (10.0.26100.7920) -OS uptime: 16 days 18:33 hours -Hyper-V role detected - -CPU: total 18 (initial active 18) (9 cores per cpu, 2 threads per core) family 6 model 170 stepping 4 microcode 0x1f, cx8, cmov, fxsr, ht, mmx, 3dnowpref, sse, sse2, sse3, ssse3, sse4.1, sse4.2, popcnt, lzcnt, tsc, tscinvbit, avx, avx2, aes, erms, clmul, bmi1, bmi2, adx, sha, fma, vzeroupper, clflush, clflushopt, clwb, hv, serialize, rdtscp, rdpid, fsrm, f16c, cet_ibt, cet_ss -Processor Information for processor 0 - Max Mhz: 1200, Current Mhz: 1200, Mhz Limit: 1200 -Processor Information for processor 1 - Max Mhz: 1200, Current Mhz: 1200, Mhz Limit: 1200 -Processor Information for processor 2 - Max Mhz: 3600, Current Mhz: 700, Mhz Limit: 684 -Processor Information for processor 3 - Max Mhz: 3600, Current Mhz: 700, Mhz Limit: 684 -Processor Information for processor 4 - Max Mhz: 3600, Current Mhz: 700, Mhz Limit: 684 -Processor Information for processor 5 - Max Mhz: 3600, Current Mhz: 700, Mhz Limit: 684 -Processor Information for processor 6 - Max Mhz: 3600, Current Mhz: 700, Mhz Limit: 684 -Processor Information for processor 7 - Max Mhz: 3600, Current Mhz: 700, Mhz Limit: 684 -Processor Information for processor 8 - Max Mhz: 3600, Current Mhz: 700, Mhz Limit: 684 -Processor Information for processor 9 - Max Mhz: 3600, Current Mhz: 700, Mhz Limit: 684 -Processor Information for processor 10 - Max Mhz: 1200, Current Mhz: 1200, Mhz Limit: 1200 -Processor Information for processor 11 - Max Mhz: 1200, Current Mhz: 1200, Mhz Limit: 1200 -Processor Information for processor 12 - Max Mhz: 1200, Current Mhz: 1200, Mhz Limit: 1200 -Processor Information for processor 13 - Max Mhz: 1200, Current Mhz: 1200, Mhz Limit: 1200 -Processor Information for processor 14 - Max Mhz: 1200, Current Mhz: 1200, Mhz Limit: 1200 -Processor Information for processor 15 - Max Mhz: 1200, Current Mhz: 1200, Mhz Limit: 1200 -Processor Information for processor 16 - Max Mhz: 2500, Current Mhz: 700, Mhz Limit: 700 -Processor Information for processor 17 - Max Mhz: 2500, Current Mhz: 700, Mhz Limit: 700 - -Memory: 4k page, system-wide physical 32346M (3826M free) -TotalPageFile size 61970M (AvailPageFile size 310M) -current process WorkingSet (physical memory assigned to process): 13M, peak: 13M -current process commit charge ("private bytes"): 68M, peak: 576M - -vm_info: OpenJDK 64-Bit Server VM (21.0.10+7-LTS) for windows-amd64 JRE (21.0.10+7-LTS), built on 2026-01-15T22:13:46Z by "Administrator" with MS VC++ 17.14 (VS2022) - -END. diff --git a/hs_err_pid192028.log b/hs_err_pid192028.log deleted file mode 100644 index cd8d3a59..00000000 --- a/hs_err_pid192028.log +++ /dev/null @@ -1,281 +0,0 @@ -# -# There is insufficient memory for the Java Runtime Environment to continue. -# Native memory allocation (mmap) failed to map 532676608 bytes. Error detail: G1 virtual space -# Possible reasons: -# The system is out of physical RAM or swap space -# This process is running with CompressedOops enabled, and the Java Heap may be blocking the growth of the native heap -# Possible solutions: -# Reduce memory load on the system -# Increase physical memory or swap space -# Check if swap backing store is full -# Decrease Java heap size (-Xmx/-Xms) -# Decrease number of Java threads -# Decrease Java thread stack sizes (-Xss) -# Set larger code cache with -XX:ReservedCodeCacheSize= -# JVM is running with Zero Based Compressed Oops mode in which the Java heap is -# placed in the first 32GB address space. The Java Heap base address is the -# maximum limit for the native heap growth. Please use -XX:HeapBaseMinAddress -# to set the Java Heap base and to place the Java Heap above 32GB virtual address. -# This output file may be truncated or incomplete. -# -# Out of Memory Error (os_windows.cpp:3714), pid=192028, tid=189352 -# -# JRE version: (21.0.10+7) (build ) -# Java VM: OpenJDK 64-Bit Server VM (21.0.10+7-LTS, mixed mode, emulated-client, sharing, tiered, compressed oops, compressed class ptrs, g1 gc, windows-amd64) -# No core dump will be written. Minidumps are not enabled by default on client versions of Windows -# - ---------------- S U M M A R Y ------------ - -Command Line: -XX:TieredStopAtLevel=1 -Dspring.profiles.active=local -Dspring.output.ansi.enabled=always -Dcom.sun.management.jmxremote -Dspring.jmx.enabled=true -Dspring.liveBeansView.mbeanDomain -Dspring.application.admin.enabled=true -Dmanagement.endpoints.jmx.exposure.include=* -javaagent:C:\Users\guswn\AppData\Local\Programs\IntelliJ IDEA\lib\idea_rt.jar=55095 -Dfile.encoding=UTF-8 -Dsun.stdout.encoding=UTF-8 -Dsun.stderr.encoding=UTF-8 com.swyp.picke.PickeApplication - -Host: Intel(R) Core(TM) Ultra 5 125H, 18 cores, 31G, Windows 11 , 64 bit Build 26100 (10.0.26100.7920) -Time: Mon Mar 30 22:58:20 2026 elapsed time: 2.059801 seconds (0d 0h 0m 2s) - ---------------- T H R E A D --------------- - -Current thread (0x0000012fb4ed3030): JavaThread "Unknown thread" [_thread_in_vm, id=189352, stack(0x00000005f8500000,0x00000005f8600000) (1024K)] - -Stack: [0x00000005f8500000,0x00000005f8600000] -Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code) -V [jvm.dll+0x6df2b9] -V [jvm.dll+0x8bbdeb] -V [jvm.dll+0x8be37a] -V [jvm.dll+0x8bea53] -V [jvm.dll+0x28a7a6] -V [jvm.dll+0x6dbc15] -V [jvm.dll+0x6cfbca] -V [jvm.dll+0x364f6e] -V [jvm.dll+0x36ce3b] -V [jvm.dll+0x3be8d9] -V [jvm.dll+0x3beb7b] -V [jvm.dll+0x339137] -V [jvm.dll+0x339c7b] -V [jvm.dll+0x88634e] -V [jvm.dll+0x3cb831] -V [jvm.dll+0x86f25c] -V [jvm.dll+0x45e901] -V [jvm.dll+0x460541] -C [jli.dll+0x52f0] -C [ucrtbase.dll+0x37b0] -C [KERNEL32.DLL+0x2e8d7] -C [ntdll.dll+0x8c48c] - - ---------------- P R O C E S S --------------- - -Threads class SMR info: -_java_thread_list=0x00007ffa227e2208, length=0, elements={ -} - -Java Threads: ( => current thread ) -Total: 0 - -Other Threads: - 0x0000012fcd0203f0 WorkerThread "GC Thread#0" [id=193216, stack(0x00000005f8600000,0x00000005f8700000) (1024K)] - 0x0000012fb7315ca0 ConcurrentGCThread "G1 Main Marker" [id=154308, stack(0x00000005f8700000,0x00000005f8800000) (1024K)] - 0x0000012fb73180e0 WorkerThread "G1 Conc#0" [id=191576, stack(0x00000005f8800000,0x00000005f8900000) (1024K)] - -[error occurred during error reporting (printing all threads), id 0xc0000005, EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x00007ffa21edbbb7] -VM state: not at safepoint (not fully initialized) - -VM Mutex/Monitor currently owned by a thread: ([mutex/lock_event]) -[0x00007ffa228566b0] Heap_lock - owner thread: 0x0000012fb4ed3030 - -Heap address: 0x0000000606800000, size: 8088 MB, Compressed Oops mode: Zero based, Oop shift amount: 3 - -CDS archive(s) mapped at: [0x0000000000000000-0x0000000000000000-0x0000000000000000), size 0, SharedBaseAddress: 0x0000000800000000, ArchiveRelocationMode: 1. -Narrow klass base: 0x0000000000000000, Narrow klass shift: 0, Narrow klass range: 0x0 - -GC Precious Log: - CardTable entry size: 512 - Card Set container configuration: InlinePtr #cards 4 size 8 Array Of Cards #cards 32 size 80 Howl #buckets 8 coarsen threshold 7372 Howl Bitmap #cards 1024 size 144 coarsen threshold 921 Card regions per heap region 1 cards per card region 8192 - -Heap: - garbage-first heap total 0K, used 0K [0x0000000606800000, 0x0000000800000000) - region size 4096K, 0 young (0K), 0 survivors (0K) - -[error occurred during error reporting (printing heap information), id 0xc0000005, EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x00007ffa222c9019] -GC Heap History (0 events): -No events - -Dll operation events (1 events): -Event: 0.044 Loaded shared library D:\application\.jdk\bin\java.dll - -Deoptimization events (0 events): -No events - -Classes loaded (0 events): -No events - -Classes unloaded (0 events): -No events - -Classes redefined (0 events): -No events - -Internal exceptions (0 events): -No events - -ZGC Phase Switch (0 events): -No events - -VM Operations (0 events): -No events - -Memory protections (0 events): -No events - -Nmethod flushes (0 events): -No events - -Events (0 events): -No events - - -Dynamic libraries: -0x00007ff7fbf60000 - 0x00007ff7fbf6e000 D:\application\.jdk\bin\java.exe -0x00007ffb03b00000 - 0x00007ffb03d67000 C:\WINDOWS\SYSTEM32\ntdll.dll -0x00007ffb02ce0000 - 0x00007ffb02da9000 C:\WINDOWS\System32\KERNEL32.DLL -0x00007ffb00fa0000 - 0x00007ffb01391000 C:\WINDOWS\System32\KERNELBASE.dll -0x00007ffb003e0000 - 0x00007ffb0052b000 C:\WINDOWS\System32\ucrtbase.dll -0x00007ffaeab10000 - 0x00007ffaeab2e000 D:\application\.jdk\bin\VCRUNTIME140.dll -0x00007ffae63b0000 - 0x00007ffae63c8000 D:\application\.jdk\bin\jli.dll -0x00007ffb02db0000 - 0x00007ffb02f75000 C:\WINDOWS\System32\USER32.dll -0x00007ffae7290000 - 0x00007ffae7523000 C:\WINDOWS\WinSxS\amd64_microsoft.windows.common-controls_6595b64144ccf1df_6.0.26100.8037_none_3e092faae333b53b\COMCTL32.dll -0x00007ffb015c0000 - 0x00007ffb015e7000 C:\WINDOWS\System32\win32u.dll -0x00007ffb031a0000 - 0x00007ffb03249000 C:\WINDOWS\System32\msvcrt.dll -0x00007ffb02780000 - 0x00007ffb027ab000 C:\WINDOWS\System32\GDI32.dll -0x00007ffb01770000 - 0x00007ffb0189b000 C:\WINDOWS\System32\gdi32full.dll -0x00007ffb005f0000 - 0x00007ffb00693000 C:\WINDOWS\System32\msvcp_win.dll -0x00007ffb03160000 - 0x00007ffb03191000 C:\WINDOWS\System32\IMM32.DLL -0x00007ffaecfa0000 - 0x00007ffaecfac000 D:\application\.jdk\bin\vcruntime140_1.dll -0x00007ffad39c0000 - 0x00007ffad3a49000 D:\application\.jdk\bin\msvcp140.dll -0x00007ffa21b90000 - 0x00007ffa22938000 D:\application\.jdk\bin\server\jvm.dll -0x00007ffb01d30000 - 0x00007ffb01deb000 C:\WINDOWS\System32\ADVAPI32.dll -0x00007ffb03250000 - 0x00007ffb032f7000 C:\WINDOWS\System32\sechost.dll -0x00007ffb024a0000 - 0x00007ffb025b8000 C:\WINDOWS\System32\RPCRT4.dll -0x00007ffb029a0000 - 0x00007ffb02a14000 C:\WINDOWS\System32\WS2_32.dll -0x00007ffb00240000 - 0x00007ffb0029e000 C:\WINDOWS\SYSTEM32\POWRPROF.dll -0x00007ffaec6c0000 - 0x00007ffaec6f5000 C:\WINDOWS\SYSTEM32\WINMM.dll -0x00007ffae7a30000 - 0x00007ffae7a3b000 C:\WINDOWS\SYSTEM32\VERSION.dll -0x00007ffb00220000 - 0x00007ffb00234000 C:\WINDOWS\SYSTEM32\UMPDC.dll -0x00007ffaff170000 - 0x00007ffaff18b000 C:\WINDOWS\SYSTEM32\kernel.appcore.dll -0x00007ffaea260000 - 0x00007ffaea26a000 D:\application\.jdk\bin\jimage.dll -0x00007ffafe4f0000 - 0x00007ffafe732000 C:\WINDOWS\SYSTEM32\DBGHELP.DLL -0x00007ffb01e50000 - 0x00007ffb021d2000 C:\WINDOWS\System32\combase.dll -0x00007ffb02f80000 - 0x00007ffb03057000 C:\WINDOWS\System32\OLEAUT32.dll -0x00007ffada3d0000 - 0x00007ffada40b000 C:\WINDOWS\SYSTEM32\dbgcore.DLL -0x00007ffb013a0000 - 0x00007ffb01445000 C:\WINDOWS\System32\bcryptPrimitives.dll -0x00007ffae63a0000 - 0x00007ffae63b0000 D:\application\.jdk\bin\instrument.dll -0x00007ffae6310000 - 0x00007ffae6331000 D:\application\.jdk\bin\java.dll - -JVMTI agents: -C:\Users\guswn\AppData\Local\Programs\IntelliJ IDEA\lib\idea_rt.jar path:none, loaded, not initialized, instrumentlib options:55095 - -dbghelp: loaded successfully - version: 4.0.5 - missing functions: none -symbol engine: initialized successfully - sym options: 0x614 - pdb path: .;D:\application\.jdk\bin;C:\WINDOWS\SYSTEM32;C:\WINDOWS\WinSxS\amd64_microsoft.windows.common-controls_6595b64144ccf1df_6.0.26100.8037_none_3e092faae333b53b;D:\application\.jdk\bin\server - -VM Arguments: -jvm_args: -XX:TieredStopAtLevel=1 -Dspring.profiles.active=local -Dspring.output.ansi.enabled=always -Dcom.sun.management.jmxremote -Dspring.jmx.enabled=true -Dspring.liveBeansView.mbeanDomain -Dspring.application.admin.enabled=true -Dmanagement.endpoints.jmx.exposure.include=* -javaagent:C:\Users\guswn\AppData\Local\Programs\IntelliJ IDEA\lib\idea_rt.jar=55095 -Dfile.encoding=UTF-8 -Dsun.stdout.encoding=UTF-8 -Dsun.stderr.encoding=UTF-8 -java_command: com.swyp.picke.PickeApplication -java_class_path (initial): D:\Desktop\project\Server\build\classes\java\main;D:\Desktop\project\Server\build\resources\main;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.projectlombok\lombok\1.18.42\8365263844ebb62398e0dc33057ba10ba472d3b8\lombok-1.18.42.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter-web\3.5.11\68fde4c94249e92526105a93ac7c22bd89b6945e\spring-boot-starter-web-3.5.11.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springdoc\springdoc-openapi-starter-webmvc-ui\2.8.16\61c68f705d3f17e8318fb18b2904fa6368af251c\springdoc-openapi-starter-webmvc-ui-2.8.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter-validation\3.5.11\903eefb6eab302617b0f01cc6d65664343bff2a7\spring-boot-starter-validation-3.5.11.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter-data-jpa\3.5.11\f176e5c643720818ec7910e1dd2ccb402411cc5d\spring-boot-starter-data-jpa-3.5.11.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter-security\3.5.11\db8b6b7951883dea3ce7404f20d6816104cedd4e\spring-boot-starter-security-3.5.11.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.jsonwebtoken\jjwt-api\0.12.6\478886a888f6add04937baf0361144504a024967\jjwt-api-0.12.6.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter-webflux\3.5.11\1461f9a6b6b8397ad71a98c9bbf4278159fb9624\spring-boot-starter-webflux-3.5.11.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.crypto.tink\apps-rewardedads\1.9.1\cbaf11457b36fe57d90a5cb16a76833906486503\apps-rewardedads-1.9.1.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.cloud\google-cloud-texttospeech\2.58.0\9be37bd3c81c14c72c9cbcfa2dfaf6dad7a35075\google-cloud-texttospeech-2.58.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.awspring.cloud\spring-cloud-aws-starter-s3\3.3.0\fa9790f990ab540814aafdbf2e97c8cd53b5b1a6\spring-cloud-aws-starter-s3-3.3.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter-thymeleaf\3.5.11\d997aa0df579cf43507d425057940e2712e44808\spring-boot-starter-thymeleaf-3.5.11.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter-json\3.5.11\4cdcd68dcddf0a4c645166e39c3fe448fe2b8e98\spring-boot-starter-json-3.5.11.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter\3.5.11\10ce971300fd56d6be5f1cfe7d27ddfb1ed7158d\spring-boot-starter-3.5.11.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter-tomcat\3.5.11\fb7b96cb61e5fd5700aed96194562e32d166b5ef\spring-boot-starter-tomcat-3.5.11.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework\spring-webmvc\6.2.16\ff2db80406f1459fddd14a8d06d57e0e3ab69465\spring-webmvc-6.2.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework\spring-web\6.2.16\2c4355f1f7e5b8969f696cbc90f25cc22f0f2164\spring-web-6.2.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springdoc\springdoc-openapi-starter-webmvc-api\2.8.16\6e41988d84978e529c01a4cc052b761cd27d5b90\springdoc-openapi-starter-webmvc-api-2.8.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.webjars\swagger-ui\5.32.0\d04c7e3e5b8616813136fa36382a548751775528\swagger-ui-5.32.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.webjars\webjars-locator-lite\1.1.3\217ce590453251b39b72c4a9af3986998f6fdbd9\webjars-locator-lite-1.1.3.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.apache.tomcat.embed\tomcat-embed-el\10.1.52\cd94ce17c5a9937eca365eb494711efa10d49b86\tomcat-embed-el-10.1.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.hibernate.validator\hibernate-validator\8.0.3.Final\4425f554297a1c5ba03a3f30e559a9fd91048cf8\hibernate-validator-8.0.3.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter-jdbc\3.5.11\3ce801963caadf6eb29abd68f5a0fe50c9bfe211\spring-boot-starter-jdbc-3.5.11.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.hibernate.orm\hibernate-core\6.6.42.Final\996e3df4a6c67941b582e4493cb9a39c83198f1e\hibernate-core-6.6.42.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.data\spring-data-jpa\3.5.9\56081dde4f663db74ba000c1f8ab30673058c363\spring-data-jpa-3.5.9.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework\spring-aspects\6.2.16\763140a66821c494985533f29280a3b4132cf055\spring-aspects-6.2.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.security\spring-security-web\6.5.8\3db7bf41191d5b23493cca6252595405b5112b34\spring-security-web-6.5.8.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.security\spring-security-config\6.5.8\302d32eba89131c0ffd15ba0a1e465051336d42f\spring-security-config-6.5.8.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework\spring-aop\6.2.16\59250efa248420a114fe23b4ccf2fea46b804186\spring-aop-6.2.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework\spring-webflux\6.2.16\699ef8bc182893f9ed43206d372f20c4f9aa3231\spring-webflux-6.2.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter-reactor-netty\3.5.11\f98bd3e3019078679dec4f21fb63152aa2e059a7\spring-boot-starter-reactor-netty-3.5.11.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.crypto.tink\tink\1.10.0\84771b1a4bb5726f73fb8490fadb23f1d2aacd38\tink-1.10.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.code.gson\gson\2.13.2\48b8230771e573b54ce6e867a9001e75977fe78e\gson-2.13.2.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.http-client\google-http-client\1.45.3\dde98b597081b98514867c9cefa551fcdea3a28c\google-http-client-1.45.3.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.errorprone\error_prone_annotations\2.41.0\4381275efdef6ddfae38f002c31e84cd001c97f0\error_prone_annotations-2.41.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.opencensus\opencensus-contrib-http-util\0.31.1\3c13fc5715231fadb16a9b74a44d9d59c460cfa8\opencensus-contrib-http-util-0.31.1.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.guava\guava\33.4.0-jre\3fcc0a259f724c7de54a6a55ea7e26d3d5c0cac\guava-33.4.0-jre.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.grpc\grpc-api\1.69.0\965c2c7f708cd6e6ddbf1eb175c3e87e96e41297\grpc-api-1.69.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.code.findbugs\jsr305\3.0.2\25ea2e8b0c338a877313bd4672d3fe056ea78f0d\jsr305-3.0.2.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.grpc\grpc-stub\1.69.0\9e7dc30a9c2df70e25ef4b941f46187e6e178e7a\grpc-stub-1.69.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.grpc\grpc-protobuf\1.69.0\2990b4948357d4fe46aaecb47290cff102079f1e\grpc-protobuf-1.69.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.api\api-common\2.43.0\963d97d95e9bf7275cc26f0b6b72e2aa5b92c6fd\api-common-2.43.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.auto.value\auto-value-annotations\1.11.0\f0d047931d07cfbc6fa4079854f181ff62891d6f\auto-value-annotations-1.11.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\javax.annotation\javax.annotation-api\1.3.2\934c04d3cfef185a8008e7bf34331b79730a9d43\javax.annotation-api-1.3.2.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.j2objc\j2objc-annotations\3.0.0\7399e65dd7e9ff3404f4535b2f017093bdb134c7\j2objc-annotations-3.0.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.protobuf\protobuf-java\3.25.5\5ae5c9ec39930ae9b5a61b32b93288818ec05ec1\protobuf-java-3.25.5.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.api.grpc\proto-google-common-protos\2.51.0\ead75a32e6fd65740b6a69feb658254aeab3fef0\proto-google-common-protos-2.51.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.api.grpc\proto-google-cloud-texttospeech-v1\2.58.0\42f1f29876ddfa2523ebcc41dae801195fd8b3ce\proto-google-cloud-texttospeech-v1-2.58.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.api.grpc\proto-google-cloud-texttospeech-v1beta1\0.147.0\576df432a2c1181deabf21a54fdecc1a32f69f4e\proto-google-cloud-texttospeech-v1beta1-0.147.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.guava\failureaccess\1.0.2\c4a06a64e650562f30b7bf9aaec1bfed43aca12b\failureaccess-1.0.2.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.guava\listenablefuture\9999.0-empty-to-avoid-conflict-with-guava\b421526c5f297295adef1c886e5246c39d4ac629\listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.checkerframework\checker-qual\3.48.4\6b5d69a61012211d581e68699baf3beb1fd382da\checker-qual-3.48.4.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.api\gax\2.60.0\2d277e0795cb69bc14e03be068aa002539e3ef49\gax-2.60.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.auth\google-auth-library-credentials\1.31.0\b9cd5346d3a683d9a8d9786453f2419cc832a97f\google-auth-library-credentials-1.31.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.opencensus\opencensus-api\0.31.1\66a60c7201c2b8b20ce495f0295b32bb0ccbbc57\opencensus-api-0.31.1.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.grpc\grpc-context\1.69.0\cea23878872f76418dcd6df0c6eef0bf27463537\grpc-context-1.69.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.auth\google-auth-library-oauth2-http\1.31.0\df5be46d21b983aab8d0250f19b585a94bdedcde\google-auth-library-oauth2-http-1.31.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.api\gax-grpc\2.60.0\ca4d7dc8c2a85fbdba25ff3449726852e2359ae9\gax-grpc-2.60.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.grpc\grpc-inprocess\1.69.0\8ac4d2e13b48bed9624b8bc485c90f3d28820c93\grpc-inprocess-1.69.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.grpc\grpc-core\1.69.0\7dad3419dfb91a77788afcdf79e0477172784910\grpc-core-1.69.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.grpc\grpc-alts\1.69.0\6d1eac6726fd6fd177666c10fd154823b82272eb\grpc-alts-1.69.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.grpc\grpc-grpclb\1.69.0\d2c9c066693ce94805a503bc47f5b1e76f51541c\grpc-grpclb-1.69.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.conscrypt\conscrypt-openjdk-uber\2.5.2\d858f142ea189c62771c505a6548d8606ac098fe\conscrypt-openjdk-uber-2.5.2.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.grpc\grpc-auth\1.69.0\a75e19b20bb732364bdcc0979e9d7c9baa4e408e\grpc-auth-1.69.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.grpc\grpc-netty-shaded\1.69.0\99aa9789172695a4b09fe2af5f5bd0ab1be4ae85\grpc-netty-shaded-1.69.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.api\gax-httpjson\2.60.0\131d9283925337406e35561ec17bf326a9ecec1a\gax-httpjson-2.60.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.apache.httpcomponents\httpclient\4.5.14\1194890e6f56ec29177673f2f12d0b8e627dec98\httpclient-4.5.14.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\commons-codec\commons-codec\1.18.0\ee45d1cf6ec2cc2b809ff04b4dc7aec858e0df8f\commons-codec-1.18.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.apache.httpcomponents\httpcore\4.4.16\51cf043c87253c9f58b539c9f7e44c8894223850\httpcore-4.4.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.http-client\google-http-client-gson\1.45.3\29eba40245c4a4e5466f8764bd894d6a97c6694f\google-http-client-gson-1.45.3.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.protobuf\protobuf-java-util\3.25.5\38cc5ce479603e36466feda2a9f1dfdb2210ef00\protobuf-java-util-3.25.5.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.threeten\threetenbp\1.7.0\8703e893440e550295aa358281db468625bc9a05\threetenbp-1.7.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.awspring.cloud\spring-cloud-aws-starter\3.3.0\7d82d320cb1851beca3005eab2e484a38bd58a08\spring-cloud-aws-starter-3.3.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.awspring.cloud\spring-cloud-aws-s3\3.3.0\661e2914e3ad6555e20ffa262a9987c15bcc1712\spring-cloud-aws-s3-3.3.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.slf4j\slf4j-api\2.0.17\d9e58ac9c7779ba3bf8142aff6c830617a7fe60f\slf4j-api-2.0.17.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.thymeleaf\thymeleaf-spring6\3.1.3.RELEASE\4b276ea2bd536a18e44b40ff1d9f4848965ff59c\thymeleaf-spring6-3.1.3.RELEASE.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.fasterxml.jackson.datatype\jackson-datatype-jdk8\2.19.4\90d304bcdb1a4bacb6f4347be625d75300973c60\jackson-datatype-jdk8-2.19.4.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.fasterxml.jackson.datatype\jackson-datatype-jsr310\2.19.4\3cbcf2e636a6b062772299bf19a347536e58c4df\jackson-datatype-jsr310-2.19.4.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.fasterxml.jackson.module\jackson-module-parameter-names\2.19.4\502dfea4c83502f444837b3d040a51e8475f15f2\jackson-module-parameter-names-2.19.4.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.fasterxml.jackson.core\jackson-databind\2.19.4\7a39bf9257b726b90b80f27fa3f5174bc75162a5\jackson-databind-2.19.4.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-autoconfigure\3.5.11\3c7d2ec2ac3c301e95814e37fed1c86c19927fc4\spring-boot-autoconfigure-3.5.11.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot\3.5.11\8b7f6df00bfbe74d370e1d05d985a127884d2a9c\spring-boot-3.5.11.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter-logging\3.5.11\62b692ed7aee31a5670796be8b07732b6b836f4e\spring-boot-starter-logging-3.5.11.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\jakarta.annotation\jakarta.annotation-api\2.1.1\48b9bda22b091b1f48b13af03fe36db3be6e1ae3\jakarta.annotation-api-2.1.1.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework\spring-core\6.2.16\a73937f20a303e057add523915b48eb7901e1848\spring-core-6.2.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.yaml\snakeyaml\2.4\e0666b825b796f85521f02360e77f4c92c5a7a07\snakeyaml-2.4.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.apache.tomcat.embed\tomcat-embed-websocket\10.1.52\9d32b801fb474306349013fcdd8317c8cb4d739e\tomcat-embed-websocket-10.1.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.apache.tomcat.embed\tomcat-embed-core\10.1.52\f512bef2796b51299f4752f95918982c3003131d\tomcat-embed-core-10.1.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework\spring-context\6.2.16\caeae6bd50832d6ab28f707aa740e957401a5c20\spring-context-6.2.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework\spring-beans\6.2.16\990289064c810be71630fca9da8e2b6fe8f897b5\spring-beans-6.2.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework\spring-expression\6.2.16\e293ab797b1698084e56ae1f2362b315148683f6\spring-expression-6.2.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.micrometer\micrometer-observation\1.15.9\edf37b25cdfac0704d6fefa4543edb3ed1817eb0\micrometer-observation-1.15.9.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springdoc\springdoc-openapi-starter-common\2.8.16\5b702cb484981b42cfb455bd80b6ce7f49d34210\springdoc-openapi-starter-common-2.8.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.jspecify\jspecify\1.0.0\7425a601c1c7ec76645a78d22b8c6a627edee507\jspecify-1.0.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\jakarta.validation\jakarta.validation-api\3.0.2\92b6631659ba35ca09e44874d3eb936edfeee532\jakarta.validation-api-3.0.2.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.jboss.logging\jboss-logging\3.6.2.Final\3e0a139d7a74cc13b5e01daa8aaa7f71dccd577e\jboss-logging-3.6.2.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.fasterxml\classmate\1.7.3\f61c7e7b81e9249b0f6a05914eff9d54fb09f4a0\classmate-1.7.3.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.zaxxer\HikariCP\6.3.3\7c5aec1e47a97ff40977e0193018865304ea9585\HikariCP-6.3.3.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework\spring-jdbc\6.2.16\addfdde7b3212f34c95d791c37bb04ba4b08a1b7\spring-jdbc-6.2.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\jakarta.persistence\jakarta.persistence-api\3.1.0\66901fa1c373c6aff65c13791cc11da72060a8d6\jakarta.persistence-api-3.1.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\jakarta.transaction\jakarta.transaction-api\2.0.1\51a520e3fae406abb84e2e1148e6746ce3f80a1a\jakarta.transaction-api-2.0.1.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.data\spring-data-commons\3.5.9\6b577c71f563e78a7da984a3d572fde8a4df8103\spring-data-commons-3.5.9.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework\spring-orm\6.2.16\44b3cfb2c046440f83729641c929c405dc7f2c89\spring-orm-6.2.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework\spring-tx\6.2.16\5f9d6e78b76530e6258de8a0dff991fb1ad4b9b0\spring-tx-6.2.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.antlr\antlr4-runtime\4.13.0\5a02e48521624faaf5ff4d99afc88b01686af655\antlr4-runtime-4.13.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.aspectj\aspectjweaver\1.9.25.1\a713c790da4d794c7dfb542b550d4e44898d5e23\aspectjweaver-1.9.25.1.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.security\spring-security-core\6.5.8\d052dca52e49d95d2b03f81ae4b6762eeb4c78d0\spring-security-core-6.5.8.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.projectreactor\reactor-core\3.7.16\dc7f2ba3c4fbc69678937dfe1ad45264d8a1c7be\reactor-core-3.7.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.projectreactor.netty\reactor-netty-http\1.2.15\b20bb13c95b44f1d0c148bdf1197b7d4a7e0f278\reactor-netty-http-1.2.15.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.awspring.cloud\spring-cloud-aws-autoconfigure\3.3.0\b5a0b27e91ee997f8c86e4b0c521858fdcb9dc9b\spring-cloud-aws-autoconfigure-3.3.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.awspring.cloud\spring-cloud-aws-core\3.3.0\3c501426267d8ccbaaebc9796bd5de5bc5d0702e\spring-cloud-aws-core-3.3.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\s3\2.29.52\db65bc6177b0c4514be1f9775cb2094e29e85d3c\s3-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.thymeleaf\thymeleaf\3.1.3.RELEASE\51474f2a90b282ee97dabcd159c7faf24790f373\thymeleaf-3.1.3.RELEASE.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.fasterxml.jackson.core\jackson-core\2.19.4\a720ca9b800742699e041c3890f3731fe516085e\jackson-core-2.19.4.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.fasterxml.jackson.core\jackson-annotations\2.19.4\bbb09b1e7f7f5108890270eb701cb3ddef991c05\jackson-annotations-2.19.4.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\ch.qos.logback\logback-classic\1.5.32\2b1042c50f508f2eb402bd4d22ccbdf94cc37d2e\logback-classic-1.5.32.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.apache.logging.log4j\log4j-to-slf4j\2.24.3\da1143e2a2531ee1c2d90baa98eb50a28a39d5a7\log4j-to-slf4j-2.24.3.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.slf4j\jul-to-slf4j\2.0.17\524cb6ccc2b68a57604750e1ab8b13b5a786a6aa\jul-to-slf4j-2.0.17.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework\spring-jcl\6.2.16\8af6546d28815be574f384dceb93d248e9934f90\spring-jcl-6.2.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.micrometer\micrometer-commons\1.15.9\5a38f43cdc79a309a458c8ce130fff30a2a7f59\micrometer-commons-1.15.9.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.swagger.core.v3\swagger-core-jakarta\2.2.43\500566364be54e3556bcec28922a41ca5fcc7dcd\swagger-core-jakarta-2.2.43.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.security\spring-security-crypto\6.5.8\aec1a6f6c0e06be9dff08b11e8e1f457afca44b2\spring-security-crypto-6.5.8.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.reactivestreams\reactive-streams\1.0.4\3864a1320d97d7b045f729a326e1e077661f31b7\reactive-streams-1.0.4.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.projectreactor.netty\reactor-netty-core\1.2.15\94b2ca82f310c1bf31d3038060e4572eeca1d4b2\reactor-netty-core-1.2.15.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-codec-http2\4.1.131.Final\2e4c47131c60e0bbbca067c891597b466f7033ba\netty-codec-http2-4.1.131.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-codec-http\4.1.131.Final\253d80637ed689ed309ca62371e5fb97746b165\netty-codec-http-4.1.131.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-resolver-dns-native-macos\4.1.131.Final\9e4a908c073e56caa4127f54d946e3e9a5208506\netty-resolver-dns-native-macos-4.1.131.Final-osx-x86_64.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-resolver-dns\4.1.131.Final\7714c0babe26712ccfdbc158aa64898ab909e7d8\netty-resolver-dns-4.1.131.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-transport-native-epoll\4.1.131.Final\10b7a905019c1ad5c37e8cf63d7229fb00668c1d\netty-transport-native-epoll-4.1.131.Final-linux-x86_64.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\aws-core\2.29.52\dcfa86ac727b5d4e0abad1e8b025ac2febb6382e\aws-core-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\auth\2.29.52\76f9b22a99b0de0fd31447db22a5cba4ed4b172e\auth-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\regions\2.29.52\270b31c8695739d495452d380d036c72698e623\regions-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\aws-xml-protocol\2.29.52\e7290d4528affec022bd2f3739853f774a955ac2\aws-xml-protocol-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\protocol-core\2.29.52\1a0e4a114c0943142ca395000a949ee840890fea\protocol-core-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\sdk-core\2.29.52\3f058b489fac3d091417339e02b165e72c637f61\sdk-core-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\arns\2.29.52\879712423589b58434b8831b9b75304a16983178\arns-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\profiles\2.29.52\59dd1368bff2d242d84515ec7ea8fe63bb472c4e\profiles-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\crt-core\2.29.52\6a16e04be0e8bb8a1767e0644c631dadddfdd764\crt-core-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\http-auth\2.29.52\aa4ce3ff7bcd8dcf131a4f5445455b3eb4926dcf\http-auth-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\http-auth-aws\2.29.52\1d0dbfa072bc46207066ffa498ad4ed65c52ac6d\http-auth-aws-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\http-auth-spi\2.29.52\4a64e68a88e3eef0b51819f742931f3607cdd996\http-auth-spi-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\identity-spi\2.29.52\d18449651e8798398cadab6c4b5d8594bb0281c\identity-spi-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\checksums\2.29.52\90631313060ff8ef1ab7745bb1e9740913bdcefc\checksums-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\retries-spi\2.29.52\7e2c7ad44106799491de8cced5925b6473d62e4b\retries-spi-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\http-client-spi\2.29.52\a8da4f289736c702ec6664836761412e7e1e54a2\http-client-spi-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\metrics-spi\2.29.52\92c3797208d24b2b25ab9b6d1bbab624c3af1b9c\metrics-spi-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\json-utils\2.29.52\d88c6c03061b9f3fcd17dc8456365dab67cc1597\json-utils-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\utils\2.29.52\bde94a15cd79b0240bfa10230970e2f0e4c51eba\utils-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\checksums-spi\2.29.52\537363296f035a935b7d3b50a5bef90014d38010\checksums-spi-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\endpoints-spi\2.29.52\bd702a44ad440628af93afa1ec1d7cdc56baec67\endpoints-spi-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\annotations\2.29.52\9fa958ce528b57d90db01c5015daaf7bd373e57f\annotations-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.attoparser\attoparser\2.0.7.RELEASE\e5d0e988d9124139d645bb5872b24dfa23e283cc\attoparser-2.0.7.RELEASE.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.unbescape\unbescape\1.1.6.RELEASE\7b90360afb2b860e09e8347112800d12c12b2a13\unbescape-1.1.6.RELEASE.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\ch.qos.logback\logback-core\1.5.32\fdfb3ff9a842303d4a95207294a6c6bc64e2605d\logback-core-1.5.32.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.apache.logging.log4j\log4j-api\2.24.3\b02c125db8b6d295adf72ae6e71af5d83bce2370\log4j-api-2.24.3.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.swagger.core.v3\swagger-models-jakarta\2.2.43\a68f7470eb763609878460272000f260eabc24dc\swagger-models-jakarta-2.2.43.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.fasterxml.jackson.dataformat\jackson-dataformat-yaml\2.19.4\500956daea0869bf753b94fdaa77e5dc99847d79\jackson-dataformat-yaml-2.19.4.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.apache.commons\commons-lang3\3.17.0\b17d2136f0460dcc0d2016ceefca8723bdf4ee70\commons-lang3-3.17.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.swagger.core.v3\swagger-annotations-jakarta\2.2.43\dbd40253251deabb7a628a54b4550dc4fb492f4\swagger-annotations-jakarta-2.2.43.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\jakarta.xml.bind\jakarta.xml.bind-api\4.0.4\d6d2327f3817d9a33a3b6b8f2e15a96bc2e7afdc\jakarta.xml.bind-api-4.0.4.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-handler-proxy\4.1.131.Final\5ff9e74613a9dd3ca078f06880a16c8cdc046de0\netty-handler-proxy-4.1.131.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-handler\4.1.131.Final\5ca67999f41c0a68f0b66485ceb990683a0b0694\netty-handler-4.1.131.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-codec\4.1.131.Final\1874341f7b29879c6833c17e7305272f0cdc2cb6\netty-codec-4.1.131.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-transport\4.1.131.Final\474862e0855d7a9828fab06a9c73c05387604ee3\netty-transport-4.1.131.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-buffer\4.1.131.Final\f97b636ecd9b81ae3fd1d039b69c4fd3959ecf\netty-buffer-4.1.131.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-common\4.1.131.Final\cdc659109da226b698a74b543a5b97dd0f7e6959\netty-common-4.1.131.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-resolver-dns-classes-macos\4.1.131.Final\b9d57038cc4144e36aee5898085b7f1f018d2c9f\netty-resolver-dns-classes-macos-4.1.131.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-codec-dns\4.1.131.Final\cd23e12e5c3448a1b12c8a4b8deeb4faeb5e483e\netty-codec-dns-4.1.131.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-resolver\4.1.131.Final\9db1bfd7c57b9b6aa9b5cfc61fc3304594bb6b39\netty-resolver-4.1.131.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-transport-classes-epoll\4.1.131.Final\4d7848ac709491fb14f8bce2796fc3eff4a04fd6\netty-transport-classes-epoll-4.1.131.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-transport-native-unix-common\4.1.131.Final\fa975e4751b23d50c0a60569829f31944d11d292\netty-transport-native-unix-common-4.1.131.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\retries\2.29.52\48cb57817dd88977ec71e63550673c5ce010a191\retries-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.eventstream\eventstream\1.0.1\6ff8649dffc5190366ada897ba8525a836297784\eventstream-1.0.1.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\http-auth-aws-eventstream\2.29.52\e8b723c48008bcac96e2cc34c7415bd8b581c601\http-auth-aws-eventstream-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\aws-query-protocol\2.29.52\672d7a2df481414d02eedf3a9eff45fb87f1b8a\aws-query-protocol-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\third-party-jackson-core\2.29.52\82ff600d837e83130502775a1555c45d7a3e2e1\third-party-jackson-core-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\jakarta.activation\jakarta.activation-api\2.1.4\9e5c2a0d75dde71a0bedc4dbdbe47b78a5dc50f8\jakarta.activation-api-2.1.4.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-codec-socks\4.1.131.Final\614eacc17f44d8abaeaea81f210b4980c3568262\netty-codec-socks-4.1.131.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-devtools\3.5.11\fe7dfcaf3153d049909a618a7ba7df288e80f090\spring-boot-devtools-3.5.11.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.jsonwebtoken\jjwt-impl\0.12.6\ac23673a84b6089e0369fb8ab2c69edd91cd6eb0\jjwt-impl-0.12.6.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.jsonwebtoken\jjwt-jackson\0.12.6\f141e0c1136ba17f2632858238a31ae05642dbf8\jjwt-jackson-0.12.6.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.postgresql\postgresql\42.7.10\35100a3f0899551e27af8fed4a3414619a4663b3\postgresql-42.7.10.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.h2database\h2\2.3.232\4fcc05d966ccdb2812ae8b9a718f69226c0cf4e2\h2-2.3.232.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.grpc\grpc-protobuf-lite\1.69.0\91711f27421babf868e424a64426fccb9e8bf6ec\grpc-protobuf-lite-1.69.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.checkerframework\checker-qual\3.52.0\9c17f496846ab1fca8975c6a50ceac0b3bbe63f0\checker-qual-3.52.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.android\annotations\4.1.1.4\a1678ba907bf92691d879fef34e1a187038f9259\annotations-4.1.1.4.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.codehaus.mojo\animal-sniffer-annotations\1.24\aa9ba58d30e0aad7f1808fce9c541ea3760678d8\animal-sniffer-annotations-1.24.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.grpc\grpc-util\1.69.0\1929ab12fce0c610d9d7229b8767f6abb09ebd51\grpc-util-1.69.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.perfmark\perfmark-api\0.27.0\f86f575a41b091786a4b027cd9c0c1d2e3fc1c01\perfmark-api-0.27.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.grpc\grpc-googleapis\1.69.0\1c11a033d96689a4bf3c92fe89b35f5edaef10c2\grpc-googleapis-1.69.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.grpc\grpc-xds\1.69.0\fa1d282a8ba3ae2a5dc0205d2f6a18b5606b5b62\grpc-xds-1.69.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.grpc\grpc-services\1.69.0\bcd917dad2380ee7cf4728da33816ffb9fad6b8b\grpc-services-1.69.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.re2j\re2j\1.7\2949632c1b4acce0d7784f28e3152e9cf3c2ec7a\re2j-1.7.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.hibernate.common\hibernate-commons-annotations\7.0.3.Final\e183c4be8bb41d12e9f19b374e00c34a0a85f439\hibernate-commons-annotations-7.0.3.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.smallrye\jandex\3.2.0\f17ad860f62a08487b9edabde608f8ac55c62fa7\jandex-3.2.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\net.bytebuddy\byte-buddy\1.17.8\af5735f63d00ca47a9375fae5c7471a36331c6ed\byte-buddy-1.17.8.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.glassfish.jaxb\jaxb-runtime\4.0.6\fb95ebb62564657b2fedfe165b859789ef3a8711\jaxb-runtime-4.0.6.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\jakarta.inject\jakarta.inject-api\2.0.1\4c28afe1991a941d7702fe1362c365f0a8641d1e\jakarta.inject-api-2.0.1.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.glassfish.jaxb\jaxb-core\4.0.6\8e61282303777fc98a00cc3affd0560d68748a75\jaxb-core-4.0.6.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\apache-client\2.29.52\b7ce213c946d69ab1807b3f7ecac1ce29ed60485\apache-client-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\netty-nio-client\2.29.52\20fa79ba82d3b290b12cd10ca49f0ff7608a6107\netty-nio-client-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.eclipse.angus\angus-activation\2.0.3\7f80607ea5014fef0b1779e6c33d63a88a45a563\angus-activation-2.0.3.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.glassfish.jaxb\txw2\4.0.6\4f4cd53b5ff9a2c5aa1211f15ed2569c57dfb044\txw2-4.0.6.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.sun.istack\istack-commons-runtime\4.1.2\18ec117c85f3ba0ac65409136afa8e42bc74e739\istack-commons-runtime-4.1.2.jar -Launcher Type: SUN_STANDARD - -[Global flags] - intx CICompilerCount = 12 {product} {ergonomic} - uint ConcGCThreads = 4 {product} {ergonomic} - uint G1ConcRefinementThreads = 14 {product} {ergonomic} - size_t G1HeapRegionSize = 4194304 {product} {ergonomic} - uintx GCDrainStackTargetSize = 64 {product} {ergonomic} - size_t InitialHeapSize = 532676608 {product} {ergonomic} - bool ManagementServer = true {product} {command line} - size_t MarkStackSize = 4194304 {product} {ergonomic} - size_t MaxHeapSize = 8480882688 {product} {ergonomic} - size_t MinHeapDeltaBytes = 4194304 {product} {ergonomic} - size_t MinHeapSize = 8388608 {product} {ergonomic} - uintx NonNMethodCodeHeapSize = 4096 {pd product} {ergonomic} - uintx NonProfiledCodeHeapSize = 0 {pd product} {ergonomic} - bool ProfileInterpreter = false {pd product} {command line} - uintx ProfiledCodeHeapSize = 0 {pd product} {ergonomic} - size_t SoftMaxHeapSize = 8480882688 {manageable} {ergonomic} - intx TieredStopAtLevel = 1 {product} {command line} - bool UseCompressedOops = true {product lp64_product} {ergonomic} - bool UseG1GC = true {product} {ergonomic} - bool UseLargePagesIndividualAllocation = false {pd product} {ergonomic} - -Logging: -Log output configuration: - #0: stdout all=warning uptime,level,tags foldmultilines=false - #1: stderr all=off uptime,level,tags foldmultilines=false - -Release file: - -Environment Variables: -JAVA_HOME=C:\Users\guswn\.jdks\corretto-19.0.2 -CLASSPATH=%JAVA_HOME%\lib -PATH=%JAVA_HOME%\bin;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\WINDOWS\System32\WindowsPowerShell\v1.0\;C:\WINDOWS\System32\OpenSSH\;D:\application\Git\cmd;C:\Program Files\Docker\Docker\resources\bin;D:\application\putty\;C:\Program Files\dotnet\;C:\Program Files\Bandizip\;D:\application\nodejs\;C:\Users\guswn\AppData\Local\Programs\Python\Python312\Scripts\;C:\Users\guswn\AppData\Local\Programs\Python\Python312\;C:\Users\guswn\AppData\Local\Programs\Python\Launcher\;C:\Users\guswn\AppData\Local\Microsoft\WindowsApps;D:\application\Microsoft VS Code\bin;C:\Users\guswn\AppData\Local\JetBrains\Toolbox\scripts;C:\Users\guswn\.local\bin;D:\application\IntelliJ IDEA 2025.3.2\bin;D:\application\JetBrains Gateway 2025.3.2\bin;C:\Users\guswn\AppData\Roaming\npm -USERNAME=guswn -OS=Windows_NT -PROCESSOR_IDENTIFIER=Intel64 Family 6 Model 170 Stepping 4, GenuineIntel -TMP=C:\Users\guswn\AppData\Local\Temp -TEMP=C:\Users\guswn\AppData\Local\Temp - - - - -Periodic native trim disabled - ---------------- S Y S T E M --------------- - -OS: - Windows 11 , 64 bit Build 26100 (10.0.26100.7920) -OS uptime: 16 days 18:33 hours -Hyper-V role detected - -CPU: total 18 (initial active 18) (9 cores per cpu, 2 threads per core) family 6 model 170 stepping 4 microcode 0x1f, cx8, cmov, fxsr, ht, mmx, 3dnowpref, sse, sse2, sse3, ssse3, sse4.1, sse4.2, popcnt, lzcnt, tsc, tscinvbit, avx, avx2, aes, erms, clmul, bmi1, bmi2, adx, sha, fma, vzeroupper, clflush, clflushopt, clwb, hv, serialize, rdtscp, rdpid, fsrm, f16c, cet_ibt, cet_ss -Processor Information for processor 0 - Max Mhz: 1200, Current Mhz: 1200, Mhz Limit: 1200 -Processor Information for processor 1 - Max Mhz: 1200, Current Mhz: 1200, Mhz Limit: 1200 -Processor Information for processor 2 - Max Mhz: 3600, Current Mhz: 700, Mhz Limit: 684 -Processor Information for processor 3 - Max Mhz: 3600, Current Mhz: 700, Mhz Limit: 684 -Processor Information for processor 4 - Max Mhz: 3600, Current Mhz: 700, Mhz Limit: 684 -Processor Information for processor 5 - Max Mhz: 3600, Current Mhz: 700, Mhz Limit: 684 -Processor Information for processor 6 - Max Mhz: 3600, Current Mhz: 700, Mhz Limit: 684 -Processor Information for processor 7 - Max Mhz: 3600, Current Mhz: 700, Mhz Limit: 684 -Processor Information for processor 8 - Max Mhz: 3600, Current Mhz: 700, Mhz Limit: 684 -Processor Information for processor 9 - Max Mhz: 3600, Current Mhz: 700, Mhz Limit: 684 -Processor Information for processor 10 - Max Mhz: 1200, Current Mhz: 1200, Mhz Limit: 1200 -Processor Information for processor 11 - Max Mhz: 1200, Current Mhz: 1200, Mhz Limit: 1200 -Processor Information for processor 12 - Max Mhz: 1200, Current Mhz: 1200, Mhz Limit: 1200 -Processor Information for processor 13 - Max Mhz: 1200, Current Mhz: 1200, Mhz Limit: 1200 -Processor Information for processor 14 - Max Mhz: 1200, Current Mhz: 1200, Mhz Limit: 1200 -Processor Information for processor 15 - Max Mhz: 1200, Current Mhz: 1200, Mhz Limit: 1200 -Processor Information for processor 16 - Max Mhz: 2500, Current Mhz: 700, Mhz Limit: 700 -Processor Information for processor 17 - Max Mhz: 2500, Current Mhz: 700, Mhz Limit: 700 - -Memory: 4k page, system-wide physical 32346M (3866M free) -TotalPageFile size 61970M (AvailPageFile size 362M) -current process WorkingSet (physical memory assigned to process): 13M, peak: 13M -current process commit charge ("private bytes"): 68M, peak: 576M - -vm_info: OpenJDK 64-Bit Server VM (21.0.10+7-LTS) for windows-amd64 JRE (21.0.10+7-LTS), built on 2026-01-15T22:13:46Z by "Administrator" with MS VC++ 17.14 (VS2022) - -END. From 69d105886b929c19a55658db2e8955a93fe8f5ac Mon Sep 17 00:00:00 2001 From: JOO Date: Tue, 7 Jul 2026 12:02:39 +0900 Subject: [PATCH 26/29] =?UTF-8?q?[HotFix]=20Railway=20FFmpeg=20=ED=99=98?= =?UTF-8?q?=EA=B2=BD=20=EC=98=A4=EB=A5=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- railpack.json | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 railpack.json diff --git a/railpack.json b/railpack.json new file mode 100644 index 00000000..6e969061 --- /dev/null +++ b/railpack.json @@ -0,0 +1,5 @@ +{ + "packages": { + "apt": ["ffmpeg"] + } +} \ No newline at end of file From 3250da4d4143dcb78437df9a22f6deb3c63355b6 Mon Sep 17 00:00:00 2001 From: JOO Date: Tue, 7 Jul 2026 12:04:21 +0900 Subject: [PATCH 27/29] =?UTF-8?q?[Refactor]=20FFmpeg=20=EC=8B=A4=ED=96=89?= =?UTF-8?q?=20=EA=B2=BD=EB=A1=9C=20=ED=8F=B4=EB=B0=B1=20=EB=B0=8F=20?= =?UTF-8?q?=EB=A1=9C=EA=B7=B8=20=EC=A0=95=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../infra/media/service/FFmpegService.java | 66 ++++++++++++++----- 1 file changed, 51 insertions(+), 15 deletions(-) diff --git a/src/main/java/com/swyp/picke/global/infra/media/service/FFmpegService.java b/src/main/java/com/swyp/picke/global/infra/media/service/FFmpegService.java index 6cbd1af5..ac3bc632 100644 --- a/src/main/java/com/swyp/picke/global/infra/media/service/FFmpegService.java +++ b/src/main/java/com/swyp/picke/global/infra/media/service/FFmpegService.java @@ -17,9 +17,49 @@ public class FFmpegService implements AudioProcessor { @Value("${media.ffprobe.path:ffprobe}") private String ffprobePath; + private String resolveExecutable(String configuredPath, String fallback) { + if (configuredPath == null || configuredPath.isBlank()) { + return resolveFallbackExecutable(fallback); + } + + File candidate = new File(configuredPath); + if (isAbsolutePath(configuredPath) && !candidate.exists()) { + log.warn("[FFmpeg] 설정된 실행 파일을 찾지 못해 PATH 명령어로 대체합니다: {}", configuredPath); + return resolveFallbackExecutable(fallback); + } + + return configuredPath; + } + + private boolean isAbsolutePath(String path) { + return new File(path).isAbsolute() || path.startsWith("/") || path.startsWith("\\"); + } + + private String resolveFallbackExecutable(String fallback) { + if (File.separatorChar != '\\') { + return fallback; + } + + try { + Process process = new ProcessBuilder("where.exe", fallback).start(); + try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) { + String resolved = reader.readLine(); + process.waitFor(); + if (resolved != null && !resolved.isBlank()) { + return resolved.trim(); + } + } + } catch (Exception e) { + log.debug("[FFmpeg] 대체 실행 파일 탐색 실패: {}, 원인={}", fallback, e.getMessage()); + } + + return fallback; + } + public Integer getAudioDurationMs(File audioFile) throws Exception { + String resolvedFfprobePath = resolveExecutable(ffprobePath, "ffprobe"); String[] cmd = { - ffprobePath, "-v", "error", "-show_entries", "format=duration", + resolvedFfprobePath, "-v", "error", "-show_entries", "format=duration", "-of", "default=noprint_wrappers=1:nokey=1", audioFile.getAbsolutePath() }; Process process = new ProcessBuilder(cmd).start(); @@ -31,11 +71,12 @@ public Integer getAudioDurationMs(File audioFile) throws Exception { } public File createSilenceFile(int durationMs) throws Exception { + String resolvedFfmpegPath = resolveExecutable(ffmpegPath, "ffmpeg"); File output = File.createTempFile("silence_", ".mp3"); double seconds = durationMs / 1000.0; String[] cmd = { - ffmpegPath, "-y", "-f", "lavfi", "-i", "anullsrc=r=44100:cl=mono", + resolvedFfmpegPath, "-y", "-f", "lavfi", "-i", "anullsrc=r=44100:cl=mono", "-t", String.valueOf(seconds), "-acodec", "libmp3lame", output.getAbsolutePath() }; @@ -44,15 +85,13 @@ public File createSilenceFile(int durationMs) throws Exception { } public File mergeAudioFiles(List audioFiles) throws Exception { - if (audioFiles == null || audioFiles.isEmpty()) throw new IllegalArgumentException("병합할 파일이 없습니다."); + if (audioFiles == null || audioFiles.isEmpty()) throw new IllegalArgumentException("merged audio file list is empty."); + String resolvedFfmpegPath = resolveExecutable(ffmpegPath, "ffmpeg"); - // FFmpeg에 전달할 리스트 파일 생성 (UTF-8 인코딩) File listFile = File.createTempFile("ffmpeg_list_", ".txt"); try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(listFile), "UTF-8"))) { for (File file : audioFiles) { - // 윈도우의 'C:\temp\file.mp3'를 'C:/temp/file.mp3'로 변환 String safePath = file.getAbsolutePath().replace("\\", "/"); - // FFmpeg 문법에 맞춰 file '경로' 형태로 기록 writer.write("file '" + safePath + "'"); writer.newLine(); } @@ -60,9 +99,8 @@ public File mergeAudioFiles(List audioFiles) throws Exception { File output = File.createTempFile("merged_full_", ".mp3"); - // 병합 명령어 구성 String[] cmd = { - ffmpegPath, "-y", "-f", "concat", "-safe", "0", + resolvedFfmpegPath, "-y", "-f", "concat", "-safe", "0", "-i", listFile.getAbsolutePath(), "-acodec", "libmp3lame", "-q:a", "2", output.getAbsolutePath() @@ -74,24 +112,22 @@ public File mergeAudioFiles(List audioFiles) throws Exception { } private void executeCommand(String[] cmd) throws Exception { - log.info("[FFmpeg] 명령어 실행: {}", String.join(" ", cmd)); + log.info("[FFmpeg] 명령 실행: {}", String.join(" ", cmd)); ProcessBuilder pb = new ProcessBuilder(cmd); - pb.redirectErrorStream(true); // 에러와 출력을 합침 + pb.redirectErrorStream(true); Process process = pb.start(); - // 실시간 로그 출력 (에러 원인 파악용) try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream(), "UTF-8"))) { String line; while ((line = reader.readLine()) != null) { - log.info("[FFmpeg Output] {}", line); // 문제 발생 시 로그에서 바로 확인 가능 + log.info("[FFmpeg 출력] {}", line); } } int exitCode = process.waitFor(); - if (exitCode != 0) { - log.error("[FFmpeg] 프로세스 오류 발생! Exit Code: {}", exitCode); + log.error("[FFmpeg] 프로세스 오류 발생. Exit Code: {}", exitCode); throw new RuntimeException("FFmpeg 프로세스 오류 발생. Exit Code: " + exitCode); } } -} \ No newline at end of file +} From cde2da36b585c665155e48189bd59ee6331c860c Mon Sep 17 00:00:00 2001 From: JOO Date: Tue, 7 Jul 2026 12:05:12 +0900 Subject: [PATCH 28/29] =?UTF-8?q?[Test]=20Railway=20FFmpeg=20=ED=8C=8C?= =?UTF-8?q?=EC=9D=B4=ED=94=84=EB=9D=BC=EC=9D=B8=20=EA=B2=80=EC=A6=9D=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ScenarioAudioPipelineServiceTest.java | 157 ++++++++++++++++++ 1 file changed, 157 insertions(+) create mode 100644 src/test/java/com/swyp/picke/domain/scenario/service/ScenarioAudioPipelineServiceTest.java diff --git a/src/test/java/com/swyp/picke/domain/scenario/service/ScenarioAudioPipelineServiceTest.java b/src/test/java/com/swyp/picke/domain/scenario/service/ScenarioAudioPipelineServiceTest.java new file mode 100644 index 00000000..6e0515e9 --- /dev/null +++ b/src/test/java/com/swyp/picke/domain/scenario/service/ScenarioAudioPipelineServiceTest.java @@ -0,0 +1,157 @@ +package com.swyp.picke.domain.scenario.service; + +import com.swyp.picke.domain.battle.entity.Battle; +import com.swyp.picke.domain.battle.enums.BattleCreatorType; +import com.swyp.picke.domain.battle.enums.BattleStatus; +import com.swyp.picke.domain.battle.repository.BattleRepository; +import com.swyp.picke.domain.scenario.entity.Scenario; +import com.swyp.picke.domain.scenario.entity.ScenarioNode; +import com.swyp.picke.domain.scenario.entity.Script; +import com.swyp.picke.domain.scenario.enums.AudioPathType; +import com.swyp.picke.domain.scenario.enums.CreatorType; +import com.swyp.picke.domain.scenario.enums.ScenarioStatus; +import com.swyp.picke.domain.scenario.enums.SpeakerType; +import com.swyp.picke.domain.scenario.repository.ScenarioRepository; +import com.swyp.picke.global.infra.media.service.FFmpegService; +import com.swyp.picke.global.infra.s3.service.S3UploadService; +import com.swyp.picke.global.infra.tts.service.TtsService; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.test.util.ReflectionTestUtils; + +import java.io.File; +import java.time.LocalDate; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.atomic.AtomicInteger; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +class ScenarioAudioPipelineServiceTest { + + @Mock + private ScenarioRepository scenarioRepository; + + @Mock + private TtsService ttsService; + + @Mock + private S3UploadService s3UploadService; + + @Mock + private BattleRepository battleRepository; + + private FFmpegService ffmpegService; + private ScenarioAudioPipelineService scenarioAudioPipelineService; + private final List uploadedFiles = new ArrayList<>(); + + @BeforeEach + void setUp() { + ffmpegService = new FFmpegService(); + ReflectionTestUtils.setField(ffmpegService, "ffmpegPath", "/usr/bin/ffmpeg"); + ReflectionTestUtils.setField(ffmpegService, "ffprobePath", "/usr/bin/ffprobe"); + + scenarioAudioPipelineService = new ScenarioAudioPipelineService( + scenarioRepository, + ttsService, + ffmpegService, + s3UploadService, + battleRepository + ); + } + + @AfterEach + void tearDown() { + for (File file : uploadedFiles) { + if (file != null && file.exists()) { + file.delete(); + } + } + } + + @Test + void generateAndMergeAudioAsync_usesFallbackExecutableAndCompletesUploadFlow() throws Exception { + Battle battle = Battle.builder() + .title("scenario battle") + .summary("summary") + .description("description") + .targetDate(LocalDate.now()) + .audioDuration(0) + .status(BattleStatus.PENDING) + .creatorType(BattleCreatorType.ADMIN) + .build(); + + Scenario scenario = Scenario.builder() + .battle(battle) + .isInteractive(false) + .status(ScenarioStatus.PENDING) + .creatorType(CreatorType.ADMIN) + .build(); + + ScenarioNode node = ScenarioNode.builder() + .nodeName("START") + .isStartNode(true) + .audioDuration(0) + .build(); + + Script firstScript = Script.builder() + .speakerType(SpeakerType.NARRATOR) + .speakerName("Narrator") + .text("First line") + .build(); + Script secondScript = Script.builder() + .speakerType(SpeakerType.NARRATOR) + .speakerName("Narrator") + .text("Second line") + .build(); + + node.addScript(firstScript); + node.addScript(secondScript); + scenario.addNode(node); + scenario.replaceVoiceSettings(Map.of(SpeakerType.NARRATOR, "voice-narrator")); + + when(scenarioRepository.findById(1L)).thenReturn(Optional.of(scenario)); + when(ttsService.generateTtsWithSsml(eq("First line"), eq(SpeakerType.NARRATOR), eq("voice-narrator"))) + .thenReturn(ffmpegService.createSilenceFile(1000)); + when(ttsService.generateTtsWithSsml(eq("Second line"), eq(SpeakerType.NARRATOR), eq("voice-narrator"))) + .thenReturn(ffmpegService.createSilenceFile(1000)); + + AtomicInteger chunkIndex = new AtomicInteger(); + when(s3UploadService.uploadFile(anyString(), any(File.class))).thenAnswer(invocation -> { + File file = invocation.getArgument(1, File.class); + uploadedFiles.add(file); + + String key = invocation.getArgument(0, String.class); + if (key.contains("/chunks/")) { + return "s3://scenario/chunks/" + chunkIndex.incrementAndGet() + ".mp3"; + } + return "s3://scenario/merged/common.mp3"; + }); + + scenarioAudioPipelineService.generateAndMergeAudioAsync(1L); + + assertThat(scenario.getStatus()).isEqualTo(ScenarioStatus.PUBLISHED); + assertThat(firstScript.getAudioUrl()).isEqualTo("s3://scenario/chunks/1.mp3"); + assertThat(secondScript.getAudioUrl()).isEqualTo("s3://scenario/chunks/2.mp3"); + assertThat(scenario.getAudios()).containsEntry(AudioPathType.COMMON, "s3://scenario/merged/common.mp3"); + assertThat(battle.getAudioDuration()).isNotNull().isGreaterThan(0); + + verify(ttsService, times(2)).generateTtsWithSsml(anyString(), eq(SpeakerType.NARRATOR), eq("voice-narrator")); + verify(s3UploadService, times(3)).uploadFile(anyString(), any(File.class)); + verify(battleRepository).save(battle); + verify(scenarioRepository).saveAndFlush(scenario); + } +} From 6a490c2f6b32750806682672a6dc1c69fd7dcc8f Mon Sep 17 00:00:00 2001 From: JOO Date: Tue, 7 Jul 2026 15:17:18 +0900 Subject: [PATCH 29/29] Revert "Merge remote-tracking branch 'origin/dev' into codex/main-from-dev" This reverts commit d17c6fe604aa7d2b0a981fde6d21730cfac2cb18, reversing changes made to 750bf160fbc5685a1621bf939d75ea3d25feb470. --- hs_err_pid172944.log | 281 ++++++++++++++++++ hs_err_pid189152.log | 281 ++++++++++++++++++ hs_err_pid192028.log | 281 ++++++++++++++++++ railpack.json | 5 - .../infra/media/service/FFmpegService.java | 66 +--- .../ScenarioAudioPipelineServiceTest.java | 157 ---------- 6 files changed, 858 insertions(+), 213 deletions(-) create mode 100644 hs_err_pid172944.log create mode 100644 hs_err_pid189152.log create mode 100644 hs_err_pid192028.log delete mode 100644 railpack.json delete mode 100644 src/test/java/com/swyp/picke/domain/scenario/service/ScenarioAudioPipelineServiceTest.java diff --git a/hs_err_pid172944.log b/hs_err_pid172944.log new file mode 100644 index 00000000..8707abc3 --- /dev/null +++ b/hs_err_pid172944.log @@ -0,0 +1,281 @@ +# +# There is insufficient memory for the Java Runtime Environment to continue. +# Native memory allocation (mmap) failed to map 532676608 bytes. Error detail: G1 virtual space +# Possible reasons: +# The system is out of physical RAM or swap space +# This process is running with CompressedOops enabled, and the Java Heap may be blocking the growth of the native heap +# Possible solutions: +# Reduce memory load on the system +# Increase physical memory or swap space +# Check if swap backing store is full +# Decrease Java heap size (-Xmx/-Xms) +# Decrease number of Java threads +# Decrease Java thread stack sizes (-Xss) +# Set larger code cache with -XX:ReservedCodeCacheSize= +# JVM is running with Zero Based Compressed Oops mode in which the Java heap is +# placed in the first 32GB address space. The Java Heap base address is the +# maximum limit for the native heap growth. Please use -XX:HeapBaseMinAddress +# to set the Java Heap base and to place the Java Heap above 32GB virtual address. +# This output file may be truncated or incomplete. +# +# Out of Memory Error (os_windows.cpp:3714), pid=172944, tid=186552 +# +# JRE version: (21.0.10+7) (build ) +# Java VM: OpenJDK 64-Bit Server VM (21.0.10+7-LTS, mixed mode, emulated-client, sharing, tiered, compressed oops, compressed class ptrs, g1 gc, windows-amd64) +# No core dump will be written. Minidumps are not enabled by default on client versions of Windows +# + +--------------- S U M M A R Y ------------ + +Command Line: -XX:TieredStopAtLevel=1 -Dspring.profiles.active=local -Dspring.output.ansi.enabled=always -Dcom.sun.management.jmxremote -Dspring.jmx.enabled=true -Dspring.liveBeansView.mbeanDomain -Dspring.application.admin.enabled=true -Dmanagement.endpoints.jmx.exposure.include=* -javaagent:C:\Users\guswn\AppData\Local\Programs\IntelliJ IDEA\lib\idea_rt.jar=51664 -Dfile.encoding=UTF-8 -Dsun.stdout.encoding=UTF-8 -Dsun.stderr.encoding=UTF-8 com.swyp.picke.PickeApplication + +Host: Intel(R) Core(TM) Ultra 5 125H, 18 cores, 31G, Windows 11 , 64 bit Build 26100 (10.0.26100.7920) +Time: Mon Mar 30 22:58:11 2026 elapsed time: 1.695367 seconds (0d 0h 0m 1s) + +--------------- T H R E A D --------------- + +Current thread (0x0000024510954d30): JavaThread "Unknown thread" [_thread_in_vm, id=186552, stack(0x0000007972f00000,0x0000007973000000) (1024K)] + +Stack: [0x0000007972f00000,0x0000007973000000] +Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code) +V [jvm.dll+0x6df2b9] +V [jvm.dll+0x8bbdeb] +V [jvm.dll+0x8be37a] +V [jvm.dll+0x8bea53] +V [jvm.dll+0x28a7a6] +V [jvm.dll+0x6dbc15] +V [jvm.dll+0x6cfbca] +V [jvm.dll+0x364f6e] +V [jvm.dll+0x36ce3b] +V [jvm.dll+0x3be8d9] +V [jvm.dll+0x3beb7b] +V [jvm.dll+0x339137] +V [jvm.dll+0x339c7b] +V [jvm.dll+0x88634e] +V [jvm.dll+0x3cb831] +V [jvm.dll+0x86f25c] +V [jvm.dll+0x45e901] +V [jvm.dll+0x460541] +C [jli.dll+0x52f0] +C [ucrtbase.dll+0x37b0] +C [KERNEL32.DLL+0x2e8d7] +C [ntdll.dll+0x8c48c] + + +--------------- P R O C E S S --------------- + +Threads class SMR info: +_java_thread_list=0x00007ffa227e2208, length=0, elements={ +} + +Java Threads: ( => current thread ) +Total: 0 + +Other Threads: + 0x00000245266f03f0 WorkerThread "GC Thread#0" [id=134476, stack(0x0000007973000000,0x0000007973100000) (1024K)] + 0x00000245109ce130 ConcurrentGCThread "G1 Main Marker" [id=195520, stack(0x0000007973100000,0x0000007973200000) (1024K)] + 0x00000245109d0570 WorkerThread "G1 Conc#0" [id=133400, stack(0x0000007973200000,0x0000007973300000) (1024K)] + +[error occurred during error reporting (printing all threads), id 0xc0000005, EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x00007ffa21edbbb7] +VM state: not at safepoint (not fully initialized) + +VM Mutex/Monitor currently owned by a thread: ([mutex/lock_event]) +[0x00007ffa228566b0] Heap_lock - owner thread: 0x0000024510954d30 + +Heap address: 0x0000000606800000, size: 8088 MB, Compressed Oops mode: Zero based, Oop shift amount: 3 + +CDS archive(s) mapped at: [0x0000000000000000-0x0000000000000000-0x0000000000000000), size 0, SharedBaseAddress: 0x0000000800000000, ArchiveRelocationMode: 1. +Narrow klass base: 0x0000000000000000, Narrow klass shift: 0, Narrow klass range: 0x0 + +GC Precious Log: + CardTable entry size: 512 + Card Set container configuration: InlinePtr #cards 4 size 8 Array Of Cards #cards 32 size 80 Howl #buckets 8 coarsen threshold 7372 Howl Bitmap #cards 1024 size 144 coarsen threshold 921 Card regions per heap region 1 cards per card region 8192 + +Heap: + garbage-first heap total 0K, used 0K [0x0000000606800000, 0x0000000800000000) + region size 4096K, 0 young (0K), 0 survivors (0K) + +[error occurred during error reporting (printing heap information), id 0xc0000005, EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x00007ffa222c9019] +GC Heap History (0 events): +No events + +Dll operation events (1 events): +Event: 0.007 Loaded shared library D:\application\.jdk\bin\java.dll + +Deoptimization events (0 events): +No events + +Classes loaded (0 events): +No events + +Classes unloaded (0 events): +No events + +Classes redefined (0 events): +No events + +Internal exceptions (0 events): +No events + +ZGC Phase Switch (0 events): +No events + +VM Operations (0 events): +No events + +Memory protections (0 events): +No events + +Nmethod flushes (0 events): +No events + +Events (0 events): +No events + + +Dynamic libraries: +0x00007ff7fbf60000 - 0x00007ff7fbf6e000 D:\application\.jdk\bin\java.exe +0x00007ffb03b00000 - 0x00007ffb03d67000 C:\WINDOWS\SYSTEM32\ntdll.dll +0x00007ffb02ce0000 - 0x00007ffb02da9000 C:\WINDOWS\System32\KERNEL32.DLL +0x00007ffb00fa0000 - 0x00007ffb01391000 C:\WINDOWS\System32\KERNELBASE.dll +0x00007ffb003e0000 - 0x00007ffb0052b000 C:\WINDOWS\System32\ucrtbase.dll +0x00007ffaeab10000 - 0x00007ffaeab2e000 D:\application\.jdk\bin\VCRUNTIME140.dll +0x00007ffae63b0000 - 0x00007ffae63c8000 D:\application\.jdk\bin\jli.dll +0x00007ffb02db0000 - 0x00007ffb02f75000 C:\WINDOWS\System32\USER32.dll +0x00007ffae7290000 - 0x00007ffae7523000 C:\WINDOWS\WinSxS\amd64_microsoft.windows.common-controls_6595b64144ccf1df_6.0.26100.8037_none_3e092faae333b53b\COMCTL32.dll +0x00007ffb031a0000 - 0x00007ffb03249000 C:\WINDOWS\System32\msvcrt.dll +0x00007ffb015c0000 - 0x00007ffb015e7000 C:\WINDOWS\System32\win32u.dll +0x00007ffb02780000 - 0x00007ffb027ab000 C:\WINDOWS\System32\GDI32.dll +0x00007ffb01770000 - 0x00007ffb0189b000 C:\WINDOWS\System32\gdi32full.dll +0x00007ffb005f0000 - 0x00007ffb00693000 C:\WINDOWS\System32\msvcp_win.dll +0x00007ffb03160000 - 0x00007ffb03191000 C:\WINDOWS\System32\IMM32.DLL +0x00007ffaecfa0000 - 0x00007ffaecfac000 D:\application\.jdk\bin\vcruntime140_1.dll +0x00007ffad39c0000 - 0x00007ffad3a49000 D:\application\.jdk\bin\msvcp140.dll +0x00007ffa21b90000 - 0x00007ffa22938000 D:\application\.jdk\bin\server\jvm.dll +0x00007ffb01d30000 - 0x00007ffb01deb000 C:\WINDOWS\System32\ADVAPI32.dll +0x00007ffb03250000 - 0x00007ffb032f7000 C:\WINDOWS\System32\sechost.dll +0x00007ffb024a0000 - 0x00007ffb025b8000 C:\WINDOWS\System32\RPCRT4.dll +0x00007ffb029a0000 - 0x00007ffb02a14000 C:\WINDOWS\System32\WS2_32.dll +0x00007ffb00240000 - 0x00007ffb0029e000 C:\WINDOWS\SYSTEM32\POWRPROF.dll +0x00007ffaec6c0000 - 0x00007ffaec6f5000 C:\WINDOWS\SYSTEM32\WINMM.dll +0x00007ffae7a30000 - 0x00007ffae7a3b000 C:\WINDOWS\SYSTEM32\VERSION.dll +0x00007ffb00220000 - 0x00007ffb00234000 C:\WINDOWS\SYSTEM32\UMPDC.dll +0x00007ffaff170000 - 0x00007ffaff18b000 C:\WINDOWS\SYSTEM32\kernel.appcore.dll +0x00007ffaea260000 - 0x00007ffaea26a000 D:\application\.jdk\bin\jimage.dll +0x00007ffafe4f0000 - 0x00007ffafe732000 C:\WINDOWS\SYSTEM32\DBGHELP.DLL +0x00007ffb01e50000 - 0x00007ffb021d2000 C:\WINDOWS\System32\combase.dll +0x00007ffb02f80000 - 0x00007ffb03057000 C:\WINDOWS\System32\OLEAUT32.dll +0x00007ffada3d0000 - 0x00007ffada40b000 C:\WINDOWS\SYSTEM32\dbgcore.DLL +0x00007ffb013a0000 - 0x00007ffb01445000 C:\WINDOWS\System32\bcryptPrimitives.dll +0x00007ffae63a0000 - 0x00007ffae63b0000 D:\application\.jdk\bin\instrument.dll +0x00007ffae6310000 - 0x00007ffae6331000 D:\application\.jdk\bin\java.dll + +JVMTI agents: +C:\Users\guswn\AppData\Local\Programs\IntelliJ IDEA\lib\idea_rt.jar path:none, loaded, not initialized, instrumentlib options:51664 + +dbghelp: loaded successfully - version: 4.0.5 - missing functions: none +symbol engine: initialized successfully - sym options: 0x614 - pdb path: .;D:\application\.jdk\bin;C:\WINDOWS\SYSTEM32;C:\WINDOWS\WinSxS\amd64_microsoft.windows.common-controls_6595b64144ccf1df_6.0.26100.8037_none_3e092faae333b53b;D:\application\.jdk\bin\server + +VM Arguments: +jvm_args: -XX:TieredStopAtLevel=1 -Dspring.profiles.active=local -Dspring.output.ansi.enabled=always -Dcom.sun.management.jmxremote -Dspring.jmx.enabled=true -Dspring.liveBeansView.mbeanDomain -Dspring.application.admin.enabled=true -Dmanagement.endpoints.jmx.exposure.include=* -javaagent:C:\Users\guswn\AppData\Local\Programs\IntelliJ IDEA\lib\idea_rt.jar=51664 -Dfile.encoding=UTF-8 -Dsun.stdout.encoding=UTF-8 -Dsun.stderr.encoding=UTF-8 +java_command: com.swyp.picke.PickeApplication +java_class_path (initial): D:\Desktop\project\Server\build\classes\java\main;D:\Desktop\project\Server\build\resources\main;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.projectlombok\lombok\1.18.42\8365263844ebb62398e0dc33057ba10ba472d3b8\lombok-1.18.42.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter-web\3.5.11\68fde4c94249e92526105a93ac7c22bd89b6945e\spring-boot-starter-web-3.5.11.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springdoc\springdoc-openapi-starter-webmvc-ui\2.8.16\61c68f705d3f17e8318fb18b2904fa6368af251c\springdoc-openapi-starter-webmvc-ui-2.8.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter-validation\3.5.11\903eefb6eab302617b0f01cc6d65664343bff2a7\spring-boot-starter-validation-3.5.11.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter-data-jpa\3.5.11\f176e5c643720818ec7910e1dd2ccb402411cc5d\spring-boot-starter-data-jpa-3.5.11.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter-security\3.5.11\db8b6b7951883dea3ce7404f20d6816104cedd4e\spring-boot-starter-security-3.5.11.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.jsonwebtoken\jjwt-api\0.12.6\478886a888f6add04937baf0361144504a024967\jjwt-api-0.12.6.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter-webflux\3.5.11\1461f9a6b6b8397ad71a98c9bbf4278159fb9624\spring-boot-starter-webflux-3.5.11.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.crypto.tink\apps-rewardedads\1.9.1\cbaf11457b36fe57d90a5cb16a76833906486503\apps-rewardedads-1.9.1.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.cloud\google-cloud-texttospeech\2.58.0\9be37bd3c81c14c72c9cbcfa2dfaf6dad7a35075\google-cloud-texttospeech-2.58.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.awspring.cloud\spring-cloud-aws-starter-s3\3.3.0\fa9790f990ab540814aafdbf2e97c8cd53b5b1a6\spring-cloud-aws-starter-s3-3.3.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter-thymeleaf\3.5.11\d997aa0df579cf43507d425057940e2712e44808\spring-boot-starter-thymeleaf-3.5.11.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter-json\3.5.11\4cdcd68dcddf0a4c645166e39c3fe448fe2b8e98\spring-boot-starter-json-3.5.11.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter\3.5.11\10ce971300fd56d6be5f1cfe7d27ddfb1ed7158d\spring-boot-starter-3.5.11.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter-tomcat\3.5.11\fb7b96cb61e5fd5700aed96194562e32d166b5ef\spring-boot-starter-tomcat-3.5.11.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework\spring-webmvc\6.2.16\ff2db80406f1459fddd14a8d06d57e0e3ab69465\spring-webmvc-6.2.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework\spring-web\6.2.16\2c4355f1f7e5b8969f696cbc90f25cc22f0f2164\spring-web-6.2.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springdoc\springdoc-openapi-starter-webmvc-api\2.8.16\6e41988d84978e529c01a4cc052b761cd27d5b90\springdoc-openapi-starter-webmvc-api-2.8.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.webjars\swagger-ui\5.32.0\d04c7e3e5b8616813136fa36382a548751775528\swagger-ui-5.32.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.webjars\webjars-locator-lite\1.1.3\217ce590453251b39b72c4a9af3986998f6fdbd9\webjars-locator-lite-1.1.3.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.apache.tomcat.embed\tomcat-embed-el\10.1.52\cd94ce17c5a9937eca365eb494711efa10d49b86\tomcat-embed-el-10.1.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.hibernate.validator\hibernate-validator\8.0.3.Final\4425f554297a1c5ba03a3f30e559a9fd91048cf8\hibernate-validator-8.0.3.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter-jdbc\3.5.11\3ce801963caadf6eb29abd68f5a0fe50c9bfe211\spring-boot-starter-jdbc-3.5.11.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.hibernate.orm\hibernate-core\6.6.42.Final\996e3df4a6c67941b582e4493cb9a39c83198f1e\hibernate-core-6.6.42.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.data\spring-data-jpa\3.5.9\56081dde4f663db74ba000c1f8ab30673058c363\spring-data-jpa-3.5.9.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework\spring-aspects\6.2.16\763140a66821c494985533f29280a3b4132cf055\spring-aspects-6.2.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.security\spring-security-web\6.5.8\3db7bf41191d5b23493cca6252595405b5112b34\spring-security-web-6.5.8.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.security\spring-security-config\6.5.8\302d32eba89131c0ffd15ba0a1e465051336d42f\spring-security-config-6.5.8.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework\spring-aop\6.2.16\59250efa248420a114fe23b4ccf2fea46b804186\spring-aop-6.2.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework\spring-webflux\6.2.16\699ef8bc182893f9ed43206d372f20c4f9aa3231\spring-webflux-6.2.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter-reactor-netty\3.5.11\f98bd3e3019078679dec4f21fb63152aa2e059a7\spring-boot-starter-reactor-netty-3.5.11.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.crypto.tink\tink\1.10.0\84771b1a4bb5726f73fb8490fadb23f1d2aacd38\tink-1.10.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.code.gson\gson\2.13.2\48b8230771e573b54ce6e867a9001e75977fe78e\gson-2.13.2.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.http-client\google-http-client\1.45.3\dde98b597081b98514867c9cefa551fcdea3a28c\google-http-client-1.45.3.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.errorprone\error_prone_annotations\2.41.0\4381275efdef6ddfae38f002c31e84cd001c97f0\error_prone_annotations-2.41.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.opencensus\opencensus-contrib-http-util\0.31.1\3c13fc5715231fadb16a9b74a44d9d59c460cfa8\opencensus-contrib-http-util-0.31.1.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.guava\guava\33.4.0-jre\3fcc0a259f724c7de54a6a55ea7e26d3d5c0cac\guava-33.4.0-jre.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.grpc\grpc-api\1.69.0\965c2c7f708cd6e6ddbf1eb175c3e87e96e41297\grpc-api-1.69.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.code.findbugs\jsr305\3.0.2\25ea2e8b0c338a877313bd4672d3fe056ea78f0d\jsr305-3.0.2.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.grpc\grpc-stub\1.69.0\9e7dc30a9c2df70e25ef4b941f46187e6e178e7a\grpc-stub-1.69.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.grpc\grpc-protobuf\1.69.0\2990b4948357d4fe46aaecb47290cff102079f1e\grpc-protobuf-1.69.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.api\api-common\2.43.0\963d97d95e9bf7275cc26f0b6b72e2aa5b92c6fd\api-common-2.43.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.auto.value\auto-value-annotations\1.11.0\f0d047931d07cfbc6fa4079854f181ff62891d6f\auto-value-annotations-1.11.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\javax.annotation\javax.annotation-api\1.3.2\934c04d3cfef185a8008e7bf34331b79730a9d43\javax.annotation-api-1.3.2.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.j2objc\j2objc-annotations\3.0.0\7399e65dd7e9ff3404f4535b2f017093bdb134c7\j2objc-annotations-3.0.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.protobuf\protobuf-java\3.25.5\5ae5c9ec39930ae9b5a61b32b93288818ec05ec1\protobuf-java-3.25.5.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.api.grpc\proto-google-common-protos\2.51.0\ead75a32e6fd65740b6a69feb658254aeab3fef0\proto-google-common-protos-2.51.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.api.grpc\proto-google-cloud-texttospeech-v1\2.58.0\42f1f29876ddfa2523ebcc41dae801195fd8b3ce\proto-google-cloud-texttospeech-v1-2.58.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.api.grpc\proto-google-cloud-texttospeech-v1beta1\0.147.0\576df432a2c1181deabf21a54fdecc1a32f69f4e\proto-google-cloud-texttospeech-v1beta1-0.147.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.guava\failureaccess\1.0.2\c4a06a64e650562f30b7bf9aaec1bfed43aca12b\failureaccess-1.0.2.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.guava\listenablefuture\9999.0-empty-to-avoid-conflict-with-guava\b421526c5f297295adef1c886e5246c39d4ac629\listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.checkerframework\checker-qual\3.48.4\6b5d69a61012211d581e68699baf3beb1fd382da\checker-qual-3.48.4.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.api\gax\2.60.0\2d277e0795cb69bc14e03be068aa002539e3ef49\gax-2.60.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.auth\google-auth-library-credentials\1.31.0\b9cd5346d3a683d9a8d9786453f2419cc832a97f\google-auth-library-credentials-1.31.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.opencensus\opencensus-api\0.31.1\66a60c7201c2b8b20ce495f0295b32bb0ccbbc57\opencensus-api-0.31.1.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.grpc\grpc-context\1.69.0\cea23878872f76418dcd6df0c6eef0bf27463537\grpc-context-1.69.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.auth\google-auth-library-oauth2-http\1.31.0\df5be46d21b983aab8d0250f19b585a94bdedcde\google-auth-library-oauth2-http-1.31.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.api\gax-grpc\2.60.0\ca4d7dc8c2a85fbdba25ff3449726852e2359ae9\gax-grpc-2.60.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.grpc\grpc-inprocess\1.69.0\8ac4d2e13b48bed9624b8bc485c90f3d28820c93\grpc-inprocess-1.69.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.grpc\grpc-core\1.69.0\7dad3419dfb91a77788afcdf79e0477172784910\grpc-core-1.69.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.grpc\grpc-alts\1.69.0\6d1eac6726fd6fd177666c10fd154823b82272eb\grpc-alts-1.69.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.grpc\grpc-grpclb\1.69.0\d2c9c066693ce94805a503bc47f5b1e76f51541c\grpc-grpclb-1.69.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.conscrypt\conscrypt-openjdk-uber\2.5.2\d858f142ea189c62771c505a6548d8606ac098fe\conscrypt-openjdk-uber-2.5.2.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.grpc\grpc-auth\1.69.0\a75e19b20bb732364bdcc0979e9d7c9baa4e408e\grpc-auth-1.69.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.grpc\grpc-netty-shaded\1.69.0\99aa9789172695a4b09fe2af5f5bd0ab1be4ae85\grpc-netty-shaded-1.69.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.api\gax-httpjson\2.60.0\131d9283925337406e35561ec17bf326a9ecec1a\gax-httpjson-2.60.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.apache.httpcomponents\httpclient\4.5.14\1194890e6f56ec29177673f2f12d0b8e627dec98\httpclient-4.5.14.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\commons-codec\commons-codec\1.18.0\ee45d1cf6ec2cc2b809ff04b4dc7aec858e0df8f\commons-codec-1.18.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.apache.httpcomponents\httpcore\4.4.16\51cf043c87253c9f58b539c9f7e44c8894223850\httpcore-4.4.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.http-client\google-http-client-gson\1.45.3\29eba40245c4a4e5466f8764bd894d6a97c6694f\google-http-client-gson-1.45.3.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.protobuf\protobuf-java-util\3.25.5\38cc5ce479603e36466feda2a9f1dfdb2210ef00\protobuf-java-util-3.25.5.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.threeten\threetenbp\1.7.0\8703e893440e550295aa358281db468625bc9a05\threetenbp-1.7.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.awspring.cloud\spring-cloud-aws-starter\3.3.0\7d82d320cb1851beca3005eab2e484a38bd58a08\spring-cloud-aws-starter-3.3.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.awspring.cloud\spring-cloud-aws-s3\3.3.0\661e2914e3ad6555e20ffa262a9987c15bcc1712\spring-cloud-aws-s3-3.3.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.slf4j\slf4j-api\2.0.17\d9e58ac9c7779ba3bf8142aff6c830617a7fe60f\slf4j-api-2.0.17.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.thymeleaf\thymeleaf-spring6\3.1.3.RELEASE\4b276ea2bd536a18e44b40ff1d9f4848965ff59c\thymeleaf-spring6-3.1.3.RELEASE.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.fasterxml.jackson.datatype\jackson-datatype-jdk8\2.19.4\90d304bcdb1a4bacb6f4347be625d75300973c60\jackson-datatype-jdk8-2.19.4.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.fasterxml.jackson.datatype\jackson-datatype-jsr310\2.19.4\3cbcf2e636a6b062772299bf19a347536e58c4df\jackson-datatype-jsr310-2.19.4.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.fasterxml.jackson.module\jackson-module-parameter-names\2.19.4\502dfea4c83502f444837b3d040a51e8475f15f2\jackson-module-parameter-names-2.19.4.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.fasterxml.jackson.core\jackson-databind\2.19.4\7a39bf9257b726b90b80f27fa3f5174bc75162a5\jackson-databind-2.19.4.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-autoconfigure\3.5.11\3c7d2ec2ac3c301e95814e37fed1c86c19927fc4\spring-boot-autoconfigure-3.5.11.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot\3.5.11\8b7f6df00bfbe74d370e1d05d985a127884d2a9c\spring-boot-3.5.11.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter-logging\3.5.11\62b692ed7aee31a5670796be8b07732b6b836f4e\spring-boot-starter-logging-3.5.11.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\jakarta.annotation\jakarta.annotation-api\2.1.1\48b9bda22b091b1f48b13af03fe36db3be6e1ae3\jakarta.annotation-api-2.1.1.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework\spring-core\6.2.16\a73937f20a303e057add523915b48eb7901e1848\spring-core-6.2.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.yaml\snakeyaml\2.4\e0666b825b796f85521f02360e77f4c92c5a7a07\snakeyaml-2.4.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.apache.tomcat.embed\tomcat-embed-websocket\10.1.52\9d32b801fb474306349013fcdd8317c8cb4d739e\tomcat-embed-websocket-10.1.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.apache.tomcat.embed\tomcat-embed-core\10.1.52\f512bef2796b51299f4752f95918982c3003131d\tomcat-embed-core-10.1.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework\spring-context\6.2.16\caeae6bd50832d6ab28f707aa740e957401a5c20\spring-context-6.2.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework\spring-beans\6.2.16\990289064c810be71630fca9da8e2b6fe8f897b5\spring-beans-6.2.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework\spring-expression\6.2.16\e293ab797b1698084e56ae1f2362b315148683f6\spring-expression-6.2.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.micrometer\micrometer-observation\1.15.9\edf37b25cdfac0704d6fefa4543edb3ed1817eb0\micrometer-observation-1.15.9.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springdoc\springdoc-openapi-starter-common\2.8.16\5b702cb484981b42cfb455bd80b6ce7f49d34210\springdoc-openapi-starter-common-2.8.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.jspecify\jspecify\1.0.0\7425a601c1c7ec76645a78d22b8c6a627edee507\jspecify-1.0.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\jakarta.validation\jakarta.validation-api\3.0.2\92b6631659ba35ca09e44874d3eb936edfeee532\jakarta.validation-api-3.0.2.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.jboss.logging\jboss-logging\3.6.2.Final\3e0a139d7a74cc13b5e01daa8aaa7f71dccd577e\jboss-logging-3.6.2.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.fasterxml\classmate\1.7.3\f61c7e7b81e9249b0f6a05914eff9d54fb09f4a0\classmate-1.7.3.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.zaxxer\HikariCP\6.3.3\7c5aec1e47a97ff40977e0193018865304ea9585\HikariCP-6.3.3.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework\spring-jdbc\6.2.16\addfdde7b3212f34c95d791c37bb04ba4b08a1b7\spring-jdbc-6.2.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\jakarta.persistence\jakarta.persistence-api\3.1.0\66901fa1c373c6aff65c13791cc11da72060a8d6\jakarta.persistence-api-3.1.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\jakarta.transaction\jakarta.transaction-api\2.0.1\51a520e3fae406abb84e2e1148e6746ce3f80a1a\jakarta.transaction-api-2.0.1.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.data\spring-data-commons\3.5.9\6b577c71f563e78a7da984a3d572fde8a4df8103\spring-data-commons-3.5.9.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework\spring-orm\6.2.16\44b3cfb2c046440f83729641c929c405dc7f2c89\spring-orm-6.2.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework\spring-tx\6.2.16\5f9d6e78b76530e6258de8a0dff991fb1ad4b9b0\spring-tx-6.2.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.antlr\antlr4-runtime\4.13.0\5a02e48521624faaf5ff4d99afc88b01686af655\antlr4-runtime-4.13.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.aspectj\aspectjweaver\1.9.25.1\a713c790da4d794c7dfb542b550d4e44898d5e23\aspectjweaver-1.9.25.1.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.security\spring-security-core\6.5.8\d052dca52e49d95d2b03f81ae4b6762eeb4c78d0\spring-security-core-6.5.8.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.projectreactor\reactor-core\3.7.16\dc7f2ba3c4fbc69678937dfe1ad45264d8a1c7be\reactor-core-3.7.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.projectreactor.netty\reactor-netty-http\1.2.15\b20bb13c95b44f1d0c148bdf1197b7d4a7e0f278\reactor-netty-http-1.2.15.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.awspring.cloud\spring-cloud-aws-autoconfigure\3.3.0\b5a0b27e91ee997f8c86e4b0c521858fdcb9dc9b\spring-cloud-aws-autoconfigure-3.3.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.awspring.cloud\spring-cloud-aws-core\3.3.0\3c501426267d8ccbaaebc9796bd5de5bc5d0702e\spring-cloud-aws-core-3.3.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\s3\2.29.52\db65bc6177b0c4514be1f9775cb2094e29e85d3c\s3-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.thymeleaf\thymeleaf\3.1.3.RELEASE\51474f2a90b282ee97dabcd159c7faf24790f373\thymeleaf-3.1.3.RELEASE.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.fasterxml.jackson.core\jackson-core\2.19.4\a720ca9b800742699e041c3890f3731fe516085e\jackson-core-2.19.4.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.fasterxml.jackson.core\jackson-annotations\2.19.4\bbb09b1e7f7f5108890270eb701cb3ddef991c05\jackson-annotations-2.19.4.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\ch.qos.logback\logback-classic\1.5.32\2b1042c50f508f2eb402bd4d22ccbdf94cc37d2e\logback-classic-1.5.32.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.apache.logging.log4j\log4j-to-slf4j\2.24.3\da1143e2a2531ee1c2d90baa98eb50a28a39d5a7\log4j-to-slf4j-2.24.3.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.slf4j\jul-to-slf4j\2.0.17\524cb6ccc2b68a57604750e1ab8b13b5a786a6aa\jul-to-slf4j-2.0.17.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework\spring-jcl\6.2.16\8af6546d28815be574f384dceb93d248e9934f90\spring-jcl-6.2.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.micrometer\micrometer-commons\1.15.9\5a38f43cdc79a309a458c8ce130fff30a2a7f59\micrometer-commons-1.15.9.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.swagger.core.v3\swagger-core-jakarta\2.2.43\500566364be54e3556bcec28922a41ca5fcc7dcd\swagger-core-jakarta-2.2.43.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.security\spring-security-crypto\6.5.8\aec1a6f6c0e06be9dff08b11e8e1f457afca44b2\spring-security-crypto-6.5.8.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.reactivestreams\reactive-streams\1.0.4\3864a1320d97d7b045f729a326e1e077661f31b7\reactive-streams-1.0.4.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.projectreactor.netty\reactor-netty-core\1.2.15\94b2ca82f310c1bf31d3038060e4572eeca1d4b2\reactor-netty-core-1.2.15.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-codec-http2\4.1.131.Final\2e4c47131c60e0bbbca067c891597b466f7033ba\netty-codec-http2-4.1.131.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-codec-http\4.1.131.Final\253d80637ed689ed309ca62371e5fb97746b165\netty-codec-http-4.1.131.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-resolver-dns-native-macos\4.1.131.Final\9e4a908c073e56caa4127f54d946e3e9a5208506\netty-resolver-dns-native-macos-4.1.131.Final-osx-x86_64.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-resolver-dns\4.1.131.Final\7714c0babe26712ccfdbc158aa64898ab909e7d8\netty-resolver-dns-4.1.131.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-transport-native-epoll\4.1.131.Final\10b7a905019c1ad5c37e8cf63d7229fb00668c1d\netty-transport-native-epoll-4.1.131.Final-linux-x86_64.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\aws-core\2.29.52\dcfa86ac727b5d4e0abad1e8b025ac2febb6382e\aws-core-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\auth\2.29.52\76f9b22a99b0de0fd31447db22a5cba4ed4b172e\auth-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\regions\2.29.52\270b31c8695739d495452d380d036c72698e623\regions-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\aws-xml-protocol\2.29.52\e7290d4528affec022bd2f3739853f774a955ac2\aws-xml-protocol-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\protocol-core\2.29.52\1a0e4a114c0943142ca395000a949ee840890fea\protocol-core-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\sdk-core\2.29.52\3f058b489fac3d091417339e02b165e72c637f61\sdk-core-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\arns\2.29.52\879712423589b58434b8831b9b75304a16983178\arns-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\profiles\2.29.52\59dd1368bff2d242d84515ec7ea8fe63bb472c4e\profiles-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\crt-core\2.29.52\6a16e04be0e8bb8a1767e0644c631dadddfdd764\crt-core-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\http-auth\2.29.52\aa4ce3ff7bcd8dcf131a4f5445455b3eb4926dcf\http-auth-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\http-auth-aws\2.29.52\1d0dbfa072bc46207066ffa498ad4ed65c52ac6d\http-auth-aws-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\http-auth-spi\2.29.52\4a64e68a88e3eef0b51819f742931f3607cdd996\http-auth-spi-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\identity-spi\2.29.52\d18449651e8798398cadab6c4b5d8594bb0281c\identity-spi-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\checksums\2.29.52\90631313060ff8ef1ab7745bb1e9740913bdcefc\checksums-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\retries-spi\2.29.52\7e2c7ad44106799491de8cced5925b6473d62e4b\retries-spi-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\http-client-spi\2.29.52\a8da4f289736c702ec6664836761412e7e1e54a2\http-client-spi-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\metrics-spi\2.29.52\92c3797208d24b2b25ab9b6d1bbab624c3af1b9c\metrics-spi-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\json-utils\2.29.52\d88c6c03061b9f3fcd17dc8456365dab67cc1597\json-utils-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\utils\2.29.52\bde94a15cd79b0240bfa10230970e2f0e4c51eba\utils-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\checksums-spi\2.29.52\537363296f035a935b7d3b50a5bef90014d38010\checksums-spi-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\endpoints-spi\2.29.52\bd702a44ad440628af93afa1ec1d7cdc56baec67\endpoints-spi-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\annotations\2.29.52\9fa958ce528b57d90db01c5015daaf7bd373e57f\annotations-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.attoparser\attoparser\2.0.7.RELEASE\e5d0e988d9124139d645bb5872b24dfa23e283cc\attoparser-2.0.7.RELEASE.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.unbescape\unbescape\1.1.6.RELEASE\7b90360afb2b860e09e8347112800d12c12b2a13\unbescape-1.1.6.RELEASE.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\ch.qos.logback\logback-core\1.5.32\fdfb3ff9a842303d4a95207294a6c6bc64e2605d\logback-core-1.5.32.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.apache.logging.log4j\log4j-api\2.24.3\b02c125db8b6d295adf72ae6e71af5d83bce2370\log4j-api-2.24.3.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.swagger.core.v3\swagger-models-jakarta\2.2.43\a68f7470eb763609878460272000f260eabc24dc\swagger-models-jakarta-2.2.43.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.fasterxml.jackson.dataformat\jackson-dataformat-yaml\2.19.4\500956daea0869bf753b94fdaa77e5dc99847d79\jackson-dataformat-yaml-2.19.4.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.apache.commons\commons-lang3\3.17.0\b17d2136f0460dcc0d2016ceefca8723bdf4ee70\commons-lang3-3.17.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.swagger.core.v3\swagger-annotations-jakarta\2.2.43\dbd40253251deabb7a628a54b4550dc4fb492f4\swagger-annotations-jakarta-2.2.43.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\jakarta.xml.bind\jakarta.xml.bind-api\4.0.4\d6d2327f3817d9a33a3b6b8f2e15a96bc2e7afdc\jakarta.xml.bind-api-4.0.4.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-handler-proxy\4.1.131.Final\5ff9e74613a9dd3ca078f06880a16c8cdc046de0\netty-handler-proxy-4.1.131.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-handler\4.1.131.Final\5ca67999f41c0a68f0b66485ceb990683a0b0694\netty-handler-4.1.131.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-codec\4.1.131.Final\1874341f7b29879c6833c17e7305272f0cdc2cb6\netty-codec-4.1.131.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-transport\4.1.131.Final\474862e0855d7a9828fab06a9c73c05387604ee3\netty-transport-4.1.131.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-buffer\4.1.131.Final\f97b636ecd9b81ae3fd1d039b69c4fd3959ecf\netty-buffer-4.1.131.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-common\4.1.131.Final\cdc659109da226b698a74b543a5b97dd0f7e6959\netty-common-4.1.131.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-resolver-dns-classes-macos\4.1.131.Final\b9d57038cc4144e36aee5898085b7f1f018d2c9f\netty-resolver-dns-classes-macos-4.1.131.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-codec-dns\4.1.131.Final\cd23e12e5c3448a1b12c8a4b8deeb4faeb5e483e\netty-codec-dns-4.1.131.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-resolver\4.1.131.Final\9db1bfd7c57b9b6aa9b5cfc61fc3304594bb6b39\netty-resolver-4.1.131.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-transport-classes-epoll\4.1.131.Final\4d7848ac709491fb14f8bce2796fc3eff4a04fd6\netty-transport-classes-epoll-4.1.131.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-transport-native-unix-common\4.1.131.Final\fa975e4751b23d50c0a60569829f31944d11d292\netty-transport-native-unix-common-4.1.131.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\retries\2.29.52\48cb57817dd88977ec71e63550673c5ce010a191\retries-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.eventstream\eventstream\1.0.1\6ff8649dffc5190366ada897ba8525a836297784\eventstream-1.0.1.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\http-auth-aws-eventstream\2.29.52\e8b723c48008bcac96e2cc34c7415bd8b581c601\http-auth-aws-eventstream-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\aws-query-protocol\2.29.52\672d7a2df481414d02eedf3a9eff45fb87f1b8a\aws-query-protocol-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\third-party-jackson-core\2.29.52\82ff600d837e83130502775a1555c45d7a3e2e1\third-party-jackson-core-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\jakarta.activation\jakarta.activation-api\2.1.4\9e5c2a0d75dde71a0bedc4dbdbe47b78a5dc50f8\jakarta.activation-api-2.1.4.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-codec-socks\4.1.131.Final\614eacc17f44d8abaeaea81f210b4980c3568262\netty-codec-socks-4.1.131.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-devtools\3.5.11\fe7dfcaf3153d049909a618a7ba7df288e80f090\spring-boot-devtools-3.5.11.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.jsonwebtoken\jjwt-impl\0.12.6\ac23673a84b6089e0369fb8ab2c69edd91cd6eb0\jjwt-impl-0.12.6.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.jsonwebtoken\jjwt-jackson\0.12.6\f141e0c1136ba17f2632858238a31ae05642dbf8\jjwt-jackson-0.12.6.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.postgresql\postgresql\42.7.10\35100a3f0899551e27af8fed4a3414619a4663b3\postgresql-42.7.10.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.h2database\h2\2.3.232\4fcc05d966ccdb2812ae8b9a718f69226c0cf4e2\h2-2.3.232.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.grpc\grpc-protobuf-lite\1.69.0\91711f27421babf868e424a64426fccb9e8bf6ec\grpc-protobuf-lite-1.69.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.checkerframework\checker-qual\3.52.0\9c17f496846ab1fca8975c6a50ceac0b3bbe63f0\checker-qual-3.52.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.android\annotations\4.1.1.4\a1678ba907bf92691d879fef34e1a187038f9259\annotations-4.1.1.4.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.codehaus.mojo\animal-sniffer-annotations\1.24\aa9ba58d30e0aad7f1808fce9c541ea3760678d8\animal-sniffer-annotations-1.24.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.grpc\grpc-util\1.69.0\1929ab12fce0c610d9d7229b8767f6abb09ebd51\grpc-util-1.69.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.perfmark\perfmark-api\0.27.0\f86f575a41b091786a4b027cd9c0c1d2e3fc1c01\perfmark-api-0.27.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.grpc\grpc-googleapis\1.69.0\1c11a033d96689a4bf3c92fe89b35f5edaef10c2\grpc-googleapis-1.69.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.grpc\grpc-xds\1.69.0\fa1d282a8ba3ae2a5dc0205d2f6a18b5606b5b62\grpc-xds-1.69.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.grpc\grpc-services\1.69.0\bcd917dad2380ee7cf4728da33816ffb9fad6b8b\grpc-services-1.69.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.re2j\re2j\1.7\2949632c1b4acce0d7784f28e3152e9cf3c2ec7a\re2j-1.7.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.hibernate.common\hibernate-commons-annotations\7.0.3.Final\e183c4be8bb41d12e9f19b374e00c34a0a85f439\hibernate-commons-annotations-7.0.3.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.smallrye\jandex\3.2.0\f17ad860f62a08487b9edabde608f8ac55c62fa7\jandex-3.2.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\net.bytebuddy\byte-buddy\1.17.8\af5735f63d00ca47a9375fae5c7471a36331c6ed\byte-buddy-1.17.8.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.glassfish.jaxb\jaxb-runtime\4.0.6\fb95ebb62564657b2fedfe165b859789ef3a8711\jaxb-runtime-4.0.6.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\jakarta.inject\jakarta.inject-api\2.0.1\4c28afe1991a941d7702fe1362c365f0a8641d1e\jakarta.inject-api-2.0.1.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.glassfish.jaxb\jaxb-core\4.0.6\8e61282303777fc98a00cc3affd0560d68748a75\jaxb-core-4.0.6.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\apache-client\2.29.52\b7ce213c946d69ab1807b3f7ecac1ce29ed60485\apache-client-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\netty-nio-client\2.29.52\20fa79ba82d3b290b12cd10ca49f0ff7608a6107\netty-nio-client-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.eclipse.angus\angus-activation\2.0.3\7f80607ea5014fef0b1779e6c33d63a88a45a563\angus-activation-2.0.3.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.glassfish.jaxb\txw2\4.0.6\4f4cd53b5ff9a2c5aa1211f15ed2569c57dfb044\txw2-4.0.6.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.sun.istack\istack-commons-runtime\4.1.2\18ec117c85f3ba0ac65409136afa8e42bc74e739\istack-commons-runtime-4.1.2.jar +Launcher Type: SUN_STANDARD + +[Global flags] + intx CICompilerCount = 12 {product} {ergonomic} + uint ConcGCThreads = 4 {product} {ergonomic} + uint G1ConcRefinementThreads = 14 {product} {ergonomic} + size_t G1HeapRegionSize = 4194304 {product} {ergonomic} + uintx GCDrainStackTargetSize = 64 {product} {ergonomic} + size_t InitialHeapSize = 532676608 {product} {ergonomic} + bool ManagementServer = true {product} {command line} + size_t MarkStackSize = 4194304 {product} {ergonomic} + size_t MaxHeapSize = 8480882688 {product} {ergonomic} + size_t MinHeapDeltaBytes = 4194304 {product} {ergonomic} + size_t MinHeapSize = 8388608 {product} {ergonomic} + uintx NonNMethodCodeHeapSize = 4096 {pd product} {ergonomic} + uintx NonProfiledCodeHeapSize = 0 {pd product} {ergonomic} + bool ProfileInterpreter = false {pd product} {command line} + uintx ProfiledCodeHeapSize = 0 {pd product} {ergonomic} + size_t SoftMaxHeapSize = 8480882688 {manageable} {ergonomic} + intx TieredStopAtLevel = 1 {product} {command line} + bool UseCompressedOops = true {product lp64_product} {ergonomic} + bool UseG1GC = true {product} {ergonomic} + bool UseLargePagesIndividualAllocation = false {pd product} {ergonomic} + +Logging: +Log output configuration: + #0: stdout all=warning uptime,level,tags foldmultilines=false + #1: stderr all=off uptime,level,tags foldmultilines=false + +Release file: + +Environment Variables: +JAVA_HOME=C:\Users\guswn\.jdks\corretto-19.0.2 +CLASSPATH=%JAVA_HOME%\lib +PATH=%JAVA_HOME%\bin;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\WINDOWS\System32\WindowsPowerShell\v1.0\;C:\WINDOWS\System32\OpenSSH\;D:\application\Git\cmd;C:\Program Files\Docker\Docker\resources\bin;D:\application\putty\;C:\Program Files\dotnet\;C:\Program Files\Bandizip\;D:\application\nodejs\;C:\Users\guswn\AppData\Local\Programs\Python\Python312\Scripts\;C:\Users\guswn\AppData\Local\Programs\Python\Python312\;C:\Users\guswn\AppData\Local\Programs\Python\Launcher\;C:\Users\guswn\AppData\Local\Microsoft\WindowsApps;D:\application\Microsoft VS Code\bin;C:\Users\guswn\AppData\Local\JetBrains\Toolbox\scripts;C:\Users\guswn\.local\bin;D:\application\IntelliJ IDEA 2025.3.2\bin;D:\application\JetBrains Gateway 2025.3.2\bin;C:\Users\guswn\AppData\Roaming\npm +USERNAME=guswn +OS=Windows_NT +PROCESSOR_IDENTIFIER=Intel64 Family 6 Model 170 Stepping 4, GenuineIntel +TMP=C:\Users\guswn\AppData\Local\Temp +TEMP=C:\Users\guswn\AppData\Local\Temp + + + + +Periodic native trim disabled + +--------------- S Y S T E M --------------- + +OS: + Windows 11 , 64 bit Build 26100 (10.0.26100.7920) +OS uptime: 16 days 18:33 hours +Hyper-V role detected + +CPU: total 18 (initial active 18) (9 cores per cpu, 2 threads per core) family 6 model 170 stepping 4 microcode 0x1f, cx8, cmov, fxsr, ht, mmx, 3dnowpref, sse, sse2, sse3, ssse3, sse4.1, sse4.2, popcnt, lzcnt, tsc, tscinvbit, avx, avx2, aes, erms, clmul, bmi1, bmi2, adx, sha, fma, vzeroupper, clflush, clflushopt, clwb, hv, serialize, rdtscp, rdpid, fsrm, f16c, cet_ibt, cet_ss +Processor Information for processor 0 + Max Mhz: 1200, Current Mhz: 1200, Mhz Limit: 1200 +Processor Information for processor 1 + Max Mhz: 1200, Current Mhz: 1200, Mhz Limit: 1200 +Processor Information for processor 2 + Max Mhz: 3600, Current Mhz: 700, Mhz Limit: 684 +Processor Information for processor 3 + Max Mhz: 3600, Current Mhz: 700, Mhz Limit: 684 +Processor Information for processor 4 + Max Mhz: 3600, Current Mhz: 700, Mhz Limit: 684 +Processor Information for processor 5 + Max Mhz: 3600, Current Mhz: 700, Mhz Limit: 684 +Processor Information for processor 6 + Max Mhz: 3600, Current Mhz: 700, Mhz Limit: 684 +Processor Information for processor 7 + Max Mhz: 3600, Current Mhz: 700, Mhz Limit: 684 +Processor Information for processor 8 + Max Mhz: 3600, Current Mhz: 700, Mhz Limit: 684 +Processor Information for processor 9 + Max Mhz: 3600, Current Mhz: 700, Mhz Limit: 684 +Processor Information for processor 10 + Max Mhz: 1200, Current Mhz: 1200, Mhz Limit: 1200 +Processor Information for processor 11 + Max Mhz: 1200, Current Mhz: 1200, Mhz Limit: 1200 +Processor Information for processor 12 + Max Mhz: 1200, Current Mhz: 1200, Mhz Limit: 1200 +Processor Information for processor 13 + Max Mhz: 1200, Current Mhz: 1200, Mhz Limit: 1200 +Processor Information for processor 14 + Max Mhz: 1200, Current Mhz: 1200, Mhz Limit: 1200 +Processor Information for processor 15 + Max Mhz: 1200, Current Mhz: 1200, Mhz Limit: 1200 +Processor Information for processor 16 + Max Mhz: 2500, Current Mhz: 700, Mhz Limit: 700 +Processor Information for processor 17 + Max Mhz: 2500, Current Mhz: 700, Mhz Limit: 700 + +Memory: 4k page, system-wide physical 32346M (3876M free) +TotalPageFile size 61970M (AvailPageFile size 336M) +current process WorkingSet (physical memory assigned to process): 13M, peak: 13M +current process commit charge ("private bytes"): 68M, peak: 576M + +vm_info: OpenJDK 64-Bit Server VM (21.0.10+7-LTS) for windows-amd64 JRE (21.0.10+7-LTS), built on 2026-01-15T22:13:46Z by "Administrator" with MS VC++ 17.14 (VS2022) + +END. diff --git a/hs_err_pid189152.log b/hs_err_pid189152.log new file mode 100644 index 00000000..12c25b95 --- /dev/null +++ b/hs_err_pid189152.log @@ -0,0 +1,281 @@ +# +# There is insufficient memory for the Java Runtime Environment to continue. +# Native memory allocation (mmap) failed to map 532676608 bytes. Error detail: G1 virtual space +# Possible reasons: +# The system is out of physical RAM or swap space +# This process is running with CompressedOops enabled, and the Java Heap may be blocking the growth of the native heap +# Possible solutions: +# Reduce memory load on the system +# Increase physical memory or swap space +# Check if swap backing store is full +# Decrease Java heap size (-Xmx/-Xms) +# Decrease number of Java threads +# Decrease Java thread stack sizes (-Xss) +# Set larger code cache with -XX:ReservedCodeCacheSize= +# JVM is running with Zero Based Compressed Oops mode in which the Java heap is +# placed in the first 32GB address space. The Java Heap base address is the +# maximum limit for the native heap growth. Please use -XX:HeapBaseMinAddress +# to set the Java Heap base and to place the Java Heap above 32GB virtual address. +# This output file may be truncated or incomplete. +# +# Out of Memory Error (os_windows.cpp:3714), pid=189152, tid=195204 +# +# JRE version: (21.0.10+7) (build ) +# Java VM: OpenJDK 64-Bit Server VM (21.0.10+7-LTS, mixed mode, emulated-client, sharing, tiered, compressed oops, compressed class ptrs, g1 gc, windows-amd64) +# No core dump will be written. Minidumps are not enabled by default on client versions of Windows +# + +--------------- S U M M A R Y ------------ + +Command Line: -XX:TieredStopAtLevel=1 -Dspring.profiles.active=local -Dspring.output.ansi.enabled=always -Dcom.sun.management.jmxremote -Dspring.jmx.enabled=true -Dspring.liveBeansView.mbeanDomain -Dspring.application.admin.enabled=true -Dmanagement.endpoints.jmx.exposure.include=* -javaagent:C:\Users\guswn\AppData\Local\Programs\IntelliJ IDEA\lib\idea_rt.jar=55101 -Dfile.encoding=UTF-8 -Dsun.stdout.encoding=UTF-8 -Dsun.stderr.encoding=UTF-8 com.swyp.picke.PickeApplication + +Host: Intel(R) Core(TM) Ultra 5 125H, 18 cores, 31G, Windows 11 , 64 bit Build 26100 (10.0.26100.7920) +Time: Mon Mar 30 22:58:27 2026 elapsed time: 2.032925 seconds (0d 0h 0m 2s) + +--------------- T H R E A D --------------- + +Current thread (0x0000027bde915cc0): JavaThread "Unknown thread" [_thread_in_vm, id=195204, stack(0x00000086bb400000,0x00000086bb500000) (1024K)] + +Stack: [0x00000086bb400000,0x00000086bb500000] +Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code) +V [jvm.dll+0x6df2b9] +V [jvm.dll+0x8bbdeb] +V [jvm.dll+0x8be37a] +V [jvm.dll+0x8bea53] +V [jvm.dll+0x28a7a6] +V [jvm.dll+0x6dbc15] +V [jvm.dll+0x6cfbca] +V [jvm.dll+0x364f6e] +V [jvm.dll+0x36ce3b] +V [jvm.dll+0x3be8d9] +V [jvm.dll+0x3beb7b] +V [jvm.dll+0x339137] +V [jvm.dll+0x339c7b] +V [jvm.dll+0x88634e] +V [jvm.dll+0x3cb831] +V [jvm.dll+0x86f25c] +V [jvm.dll+0x45e901] +V [jvm.dll+0x460541] +C [jli.dll+0x52f0] +C [ucrtbase.dll+0x37b0] +C [KERNEL32.DLL+0x2e8d7] +C [ntdll.dll+0x8c48c] + + +--------------- P R O C E S S --------------- + +Threads class SMR info: +_java_thread_list=0x00007ffa227e2208, length=0, elements={ +} + +Java Threads: ( => current thread ) +Total: 0 + +Other Threads: + 0x0000027bf46a03f0 WorkerThread "GC Thread#0" [id=7472, stack(0x00000086bb500000,0x00000086bb600000) (1024K)] + 0x0000027bde990120 ConcurrentGCThread "G1 Main Marker" [id=163140, stack(0x00000086bb600000,0x00000086bb700000) (1024K)] + 0x0000027bde991760 WorkerThread "G1 Conc#0" [id=152476, stack(0x00000086bb700000,0x00000086bb800000) (1024K)] + +[error occurred during error reporting (printing all threads), id 0xc0000005, EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x00007ffa21edbbb7] +VM state: not at safepoint (not fully initialized) + +VM Mutex/Monitor currently owned by a thread: ([mutex/lock_event]) +[0x00007ffa228566b0] Heap_lock - owner thread: 0x0000027bde915cc0 + +Heap address: 0x0000000606800000, size: 8088 MB, Compressed Oops mode: Zero based, Oop shift amount: 3 + +CDS archive(s) mapped at: [0x0000000000000000-0x0000000000000000-0x0000000000000000), size 0, SharedBaseAddress: 0x0000000800000000, ArchiveRelocationMode: 1. +Narrow klass base: 0x0000000000000000, Narrow klass shift: 0, Narrow klass range: 0x0 + +GC Precious Log: + CardTable entry size: 512 + Card Set container configuration: InlinePtr #cards 4 size 8 Array Of Cards #cards 32 size 80 Howl #buckets 8 coarsen threshold 7372 Howl Bitmap #cards 1024 size 144 coarsen threshold 921 Card regions per heap region 1 cards per card region 8192 + +Heap: + garbage-first heap total 0K, used 0K [0x0000000606800000, 0x0000000800000000) + region size 4096K, 0 young (0K), 0 survivors (0K) + +[error occurred during error reporting (printing heap information), id 0xc0000005, EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x00007ffa222c9019] +GC Heap History (0 events): +No events + +Dll operation events (1 events): +Event: 0.005 Loaded shared library D:\application\.jdk\bin\java.dll + +Deoptimization events (0 events): +No events + +Classes loaded (0 events): +No events + +Classes unloaded (0 events): +No events + +Classes redefined (0 events): +No events + +Internal exceptions (0 events): +No events + +ZGC Phase Switch (0 events): +No events + +VM Operations (0 events): +No events + +Memory protections (0 events): +No events + +Nmethod flushes (0 events): +No events + +Events (0 events): +No events + + +Dynamic libraries: +0x00007ff7fbf60000 - 0x00007ff7fbf6e000 D:\application\.jdk\bin\java.exe +0x00007ffb03b00000 - 0x00007ffb03d67000 C:\WINDOWS\SYSTEM32\ntdll.dll +0x00007ffb02ce0000 - 0x00007ffb02da9000 C:\WINDOWS\System32\KERNEL32.DLL +0x00007ffb00fa0000 - 0x00007ffb01391000 C:\WINDOWS\System32\KERNELBASE.dll +0x00007ffb003e0000 - 0x00007ffb0052b000 C:\WINDOWS\System32\ucrtbase.dll +0x00007ffae63b0000 - 0x00007ffae63c8000 D:\application\.jdk\bin\jli.dll +0x00007ffb02db0000 - 0x00007ffb02f75000 C:\WINDOWS\System32\USER32.dll +0x00007ffb015c0000 - 0x00007ffb015e7000 C:\WINDOWS\System32\win32u.dll +0x00007ffb02780000 - 0x00007ffb027ab000 C:\WINDOWS\System32\GDI32.dll +0x00007ffae7290000 - 0x00007ffae7523000 C:\WINDOWS\WinSxS\amd64_microsoft.windows.common-controls_6595b64144ccf1df_6.0.26100.8037_none_3e092faae333b53b\COMCTL32.dll +0x00007ffb031a0000 - 0x00007ffb03249000 C:\WINDOWS\System32\msvcrt.dll +0x00007ffb01770000 - 0x00007ffb0189b000 C:\WINDOWS\System32\gdi32full.dll +0x00007ffaeab10000 - 0x00007ffaeab2e000 D:\application\.jdk\bin\VCRUNTIME140.dll +0x00007ffb005f0000 - 0x00007ffb00693000 C:\WINDOWS\System32\msvcp_win.dll +0x00007ffb03160000 - 0x00007ffb03191000 C:\WINDOWS\System32\IMM32.DLL +0x00007ffaecfa0000 - 0x00007ffaecfac000 D:\application\.jdk\bin\vcruntime140_1.dll +0x00007ffad39c0000 - 0x00007ffad3a49000 D:\application\.jdk\bin\msvcp140.dll +0x00007ffa21b90000 - 0x00007ffa22938000 D:\application\.jdk\bin\server\jvm.dll +0x00007ffb01d30000 - 0x00007ffb01deb000 C:\WINDOWS\System32\ADVAPI32.dll +0x00007ffb03250000 - 0x00007ffb032f7000 C:\WINDOWS\System32\sechost.dll +0x00007ffb024a0000 - 0x00007ffb025b8000 C:\WINDOWS\System32\RPCRT4.dll +0x00007ffb029a0000 - 0x00007ffb02a14000 C:\WINDOWS\System32\WS2_32.dll +0x00007ffb00240000 - 0x00007ffb0029e000 C:\WINDOWS\SYSTEM32\POWRPROF.dll +0x00007ffaec6c0000 - 0x00007ffaec6f5000 C:\WINDOWS\SYSTEM32\WINMM.dll +0x00007ffae7a30000 - 0x00007ffae7a3b000 C:\WINDOWS\SYSTEM32\VERSION.dll +0x00007ffb00220000 - 0x00007ffb00234000 C:\WINDOWS\SYSTEM32\UMPDC.dll +0x00007ffaff170000 - 0x00007ffaff18b000 C:\WINDOWS\SYSTEM32\kernel.appcore.dll +0x00007ffaea260000 - 0x00007ffaea26a000 D:\application\.jdk\bin\jimage.dll +0x00007ffafe4f0000 - 0x00007ffafe732000 C:\WINDOWS\SYSTEM32\DBGHELP.DLL +0x00007ffb01e50000 - 0x00007ffb021d2000 C:\WINDOWS\System32\combase.dll +0x00007ffb02f80000 - 0x00007ffb03057000 C:\WINDOWS\System32\OLEAUT32.dll +0x00007ffada3d0000 - 0x00007ffada40b000 C:\WINDOWS\SYSTEM32\dbgcore.DLL +0x00007ffb013a0000 - 0x00007ffb01445000 C:\WINDOWS\System32\bcryptPrimitives.dll +0x00007ffae63a0000 - 0x00007ffae63b0000 D:\application\.jdk\bin\instrument.dll +0x00007ffae6310000 - 0x00007ffae6331000 D:\application\.jdk\bin\java.dll + +JVMTI agents: +C:\Users\guswn\AppData\Local\Programs\IntelliJ IDEA\lib\idea_rt.jar path:none, loaded, not initialized, instrumentlib options:55101 + +dbghelp: loaded successfully - version: 4.0.5 - missing functions: none +symbol engine: initialized successfully - sym options: 0x614 - pdb path: .;D:\application\.jdk\bin;C:\WINDOWS\SYSTEM32;C:\WINDOWS\WinSxS\amd64_microsoft.windows.common-controls_6595b64144ccf1df_6.0.26100.8037_none_3e092faae333b53b;D:\application\.jdk\bin\server + +VM Arguments: +jvm_args: -XX:TieredStopAtLevel=1 -Dspring.profiles.active=local -Dspring.output.ansi.enabled=always -Dcom.sun.management.jmxremote -Dspring.jmx.enabled=true -Dspring.liveBeansView.mbeanDomain -Dspring.application.admin.enabled=true -Dmanagement.endpoints.jmx.exposure.include=* -javaagent:C:\Users\guswn\AppData\Local\Programs\IntelliJ IDEA\lib\idea_rt.jar=55101 -Dfile.encoding=UTF-8 -Dsun.stdout.encoding=UTF-8 -Dsun.stderr.encoding=UTF-8 +java_command: com.swyp.picke.PickeApplication +java_class_path (initial): D:\Desktop\project\Server\build\classes\java\main;D:\Desktop\project\Server\build\resources\main;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.projectlombok\lombok\1.18.42\8365263844ebb62398e0dc33057ba10ba472d3b8\lombok-1.18.42.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter-web\3.5.11\68fde4c94249e92526105a93ac7c22bd89b6945e\spring-boot-starter-web-3.5.11.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springdoc\springdoc-openapi-starter-webmvc-ui\2.8.16\61c68f705d3f17e8318fb18b2904fa6368af251c\springdoc-openapi-starter-webmvc-ui-2.8.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter-validation\3.5.11\903eefb6eab302617b0f01cc6d65664343bff2a7\spring-boot-starter-validation-3.5.11.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter-data-jpa\3.5.11\f176e5c643720818ec7910e1dd2ccb402411cc5d\spring-boot-starter-data-jpa-3.5.11.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter-security\3.5.11\db8b6b7951883dea3ce7404f20d6816104cedd4e\spring-boot-starter-security-3.5.11.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.jsonwebtoken\jjwt-api\0.12.6\478886a888f6add04937baf0361144504a024967\jjwt-api-0.12.6.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter-webflux\3.5.11\1461f9a6b6b8397ad71a98c9bbf4278159fb9624\spring-boot-starter-webflux-3.5.11.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.crypto.tink\apps-rewardedads\1.9.1\cbaf11457b36fe57d90a5cb16a76833906486503\apps-rewardedads-1.9.1.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.cloud\google-cloud-texttospeech\2.58.0\9be37bd3c81c14c72c9cbcfa2dfaf6dad7a35075\google-cloud-texttospeech-2.58.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.awspring.cloud\spring-cloud-aws-starter-s3\3.3.0\fa9790f990ab540814aafdbf2e97c8cd53b5b1a6\spring-cloud-aws-starter-s3-3.3.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter-thymeleaf\3.5.11\d997aa0df579cf43507d425057940e2712e44808\spring-boot-starter-thymeleaf-3.5.11.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter-json\3.5.11\4cdcd68dcddf0a4c645166e39c3fe448fe2b8e98\spring-boot-starter-json-3.5.11.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter\3.5.11\10ce971300fd56d6be5f1cfe7d27ddfb1ed7158d\spring-boot-starter-3.5.11.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter-tomcat\3.5.11\fb7b96cb61e5fd5700aed96194562e32d166b5ef\spring-boot-starter-tomcat-3.5.11.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework\spring-webmvc\6.2.16\ff2db80406f1459fddd14a8d06d57e0e3ab69465\spring-webmvc-6.2.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework\spring-web\6.2.16\2c4355f1f7e5b8969f696cbc90f25cc22f0f2164\spring-web-6.2.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springdoc\springdoc-openapi-starter-webmvc-api\2.8.16\6e41988d84978e529c01a4cc052b761cd27d5b90\springdoc-openapi-starter-webmvc-api-2.8.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.webjars\swagger-ui\5.32.0\d04c7e3e5b8616813136fa36382a548751775528\swagger-ui-5.32.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.webjars\webjars-locator-lite\1.1.3\217ce590453251b39b72c4a9af3986998f6fdbd9\webjars-locator-lite-1.1.3.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.apache.tomcat.embed\tomcat-embed-el\10.1.52\cd94ce17c5a9937eca365eb494711efa10d49b86\tomcat-embed-el-10.1.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.hibernate.validator\hibernate-validator\8.0.3.Final\4425f554297a1c5ba03a3f30e559a9fd91048cf8\hibernate-validator-8.0.3.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter-jdbc\3.5.11\3ce801963caadf6eb29abd68f5a0fe50c9bfe211\spring-boot-starter-jdbc-3.5.11.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.hibernate.orm\hibernate-core\6.6.42.Final\996e3df4a6c67941b582e4493cb9a39c83198f1e\hibernate-core-6.6.42.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.data\spring-data-jpa\3.5.9\56081dde4f663db74ba000c1f8ab30673058c363\spring-data-jpa-3.5.9.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework\spring-aspects\6.2.16\763140a66821c494985533f29280a3b4132cf055\spring-aspects-6.2.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.security\spring-security-web\6.5.8\3db7bf41191d5b23493cca6252595405b5112b34\spring-security-web-6.5.8.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.security\spring-security-config\6.5.8\302d32eba89131c0ffd15ba0a1e465051336d42f\spring-security-config-6.5.8.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework\spring-aop\6.2.16\59250efa248420a114fe23b4ccf2fea46b804186\spring-aop-6.2.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework\spring-webflux\6.2.16\699ef8bc182893f9ed43206d372f20c4f9aa3231\spring-webflux-6.2.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter-reactor-netty\3.5.11\f98bd3e3019078679dec4f21fb63152aa2e059a7\spring-boot-starter-reactor-netty-3.5.11.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.crypto.tink\tink\1.10.0\84771b1a4bb5726f73fb8490fadb23f1d2aacd38\tink-1.10.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.code.gson\gson\2.13.2\48b8230771e573b54ce6e867a9001e75977fe78e\gson-2.13.2.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.http-client\google-http-client\1.45.3\dde98b597081b98514867c9cefa551fcdea3a28c\google-http-client-1.45.3.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.errorprone\error_prone_annotations\2.41.0\4381275efdef6ddfae38f002c31e84cd001c97f0\error_prone_annotations-2.41.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.opencensus\opencensus-contrib-http-util\0.31.1\3c13fc5715231fadb16a9b74a44d9d59c460cfa8\opencensus-contrib-http-util-0.31.1.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.guava\guava\33.4.0-jre\3fcc0a259f724c7de54a6a55ea7e26d3d5c0cac\guava-33.4.0-jre.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.grpc\grpc-api\1.69.0\965c2c7f708cd6e6ddbf1eb175c3e87e96e41297\grpc-api-1.69.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.code.findbugs\jsr305\3.0.2\25ea2e8b0c338a877313bd4672d3fe056ea78f0d\jsr305-3.0.2.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.grpc\grpc-stub\1.69.0\9e7dc30a9c2df70e25ef4b941f46187e6e178e7a\grpc-stub-1.69.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.grpc\grpc-protobuf\1.69.0\2990b4948357d4fe46aaecb47290cff102079f1e\grpc-protobuf-1.69.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.api\api-common\2.43.0\963d97d95e9bf7275cc26f0b6b72e2aa5b92c6fd\api-common-2.43.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.auto.value\auto-value-annotations\1.11.0\f0d047931d07cfbc6fa4079854f181ff62891d6f\auto-value-annotations-1.11.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\javax.annotation\javax.annotation-api\1.3.2\934c04d3cfef185a8008e7bf34331b79730a9d43\javax.annotation-api-1.3.2.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.j2objc\j2objc-annotations\3.0.0\7399e65dd7e9ff3404f4535b2f017093bdb134c7\j2objc-annotations-3.0.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.protobuf\protobuf-java\3.25.5\5ae5c9ec39930ae9b5a61b32b93288818ec05ec1\protobuf-java-3.25.5.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.api.grpc\proto-google-common-protos\2.51.0\ead75a32e6fd65740b6a69feb658254aeab3fef0\proto-google-common-protos-2.51.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.api.grpc\proto-google-cloud-texttospeech-v1\2.58.0\42f1f29876ddfa2523ebcc41dae801195fd8b3ce\proto-google-cloud-texttospeech-v1-2.58.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.api.grpc\proto-google-cloud-texttospeech-v1beta1\0.147.0\576df432a2c1181deabf21a54fdecc1a32f69f4e\proto-google-cloud-texttospeech-v1beta1-0.147.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.guava\failureaccess\1.0.2\c4a06a64e650562f30b7bf9aaec1bfed43aca12b\failureaccess-1.0.2.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.guava\listenablefuture\9999.0-empty-to-avoid-conflict-with-guava\b421526c5f297295adef1c886e5246c39d4ac629\listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.checkerframework\checker-qual\3.48.4\6b5d69a61012211d581e68699baf3beb1fd382da\checker-qual-3.48.4.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.api\gax\2.60.0\2d277e0795cb69bc14e03be068aa002539e3ef49\gax-2.60.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.auth\google-auth-library-credentials\1.31.0\b9cd5346d3a683d9a8d9786453f2419cc832a97f\google-auth-library-credentials-1.31.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.opencensus\opencensus-api\0.31.1\66a60c7201c2b8b20ce495f0295b32bb0ccbbc57\opencensus-api-0.31.1.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.grpc\grpc-context\1.69.0\cea23878872f76418dcd6df0c6eef0bf27463537\grpc-context-1.69.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.auth\google-auth-library-oauth2-http\1.31.0\df5be46d21b983aab8d0250f19b585a94bdedcde\google-auth-library-oauth2-http-1.31.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.api\gax-grpc\2.60.0\ca4d7dc8c2a85fbdba25ff3449726852e2359ae9\gax-grpc-2.60.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.grpc\grpc-inprocess\1.69.0\8ac4d2e13b48bed9624b8bc485c90f3d28820c93\grpc-inprocess-1.69.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.grpc\grpc-core\1.69.0\7dad3419dfb91a77788afcdf79e0477172784910\grpc-core-1.69.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.grpc\grpc-alts\1.69.0\6d1eac6726fd6fd177666c10fd154823b82272eb\grpc-alts-1.69.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.grpc\grpc-grpclb\1.69.0\d2c9c066693ce94805a503bc47f5b1e76f51541c\grpc-grpclb-1.69.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.conscrypt\conscrypt-openjdk-uber\2.5.2\d858f142ea189c62771c505a6548d8606ac098fe\conscrypt-openjdk-uber-2.5.2.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.grpc\grpc-auth\1.69.0\a75e19b20bb732364bdcc0979e9d7c9baa4e408e\grpc-auth-1.69.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.grpc\grpc-netty-shaded\1.69.0\99aa9789172695a4b09fe2af5f5bd0ab1be4ae85\grpc-netty-shaded-1.69.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.api\gax-httpjson\2.60.0\131d9283925337406e35561ec17bf326a9ecec1a\gax-httpjson-2.60.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.apache.httpcomponents\httpclient\4.5.14\1194890e6f56ec29177673f2f12d0b8e627dec98\httpclient-4.5.14.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\commons-codec\commons-codec\1.18.0\ee45d1cf6ec2cc2b809ff04b4dc7aec858e0df8f\commons-codec-1.18.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.apache.httpcomponents\httpcore\4.4.16\51cf043c87253c9f58b539c9f7e44c8894223850\httpcore-4.4.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.http-client\google-http-client-gson\1.45.3\29eba40245c4a4e5466f8764bd894d6a97c6694f\google-http-client-gson-1.45.3.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.protobuf\protobuf-java-util\3.25.5\38cc5ce479603e36466feda2a9f1dfdb2210ef00\protobuf-java-util-3.25.5.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.threeten\threetenbp\1.7.0\8703e893440e550295aa358281db468625bc9a05\threetenbp-1.7.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.awspring.cloud\spring-cloud-aws-starter\3.3.0\7d82d320cb1851beca3005eab2e484a38bd58a08\spring-cloud-aws-starter-3.3.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.awspring.cloud\spring-cloud-aws-s3\3.3.0\661e2914e3ad6555e20ffa262a9987c15bcc1712\spring-cloud-aws-s3-3.3.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.slf4j\slf4j-api\2.0.17\d9e58ac9c7779ba3bf8142aff6c830617a7fe60f\slf4j-api-2.0.17.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.thymeleaf\thymeleaf-spring6\3.1.3.RELEASE\4b276ea2bd536a18e44b40ff1d9f4848965ff59c\thymeleaf-spring6-3.1.3.RELEASE.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.fasterxml.jackson.datatype\jackson-datatype-jdk8\2.19.4\90d304bcdb1a4bacb6f4347be625d75300973c60\jackson-datatype-jdk8-2.19.4.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.fasterxml.jackson.datatype\jackson-datatype-jsr310\2.19.4\3cbcf2e636a6b062772299bf19a347536e58c4df\jackson-datatype-jsr310-2.19.4.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.fasterxml.jackson.module\jackson-module-parameter-names\2.19.4\502dfea4c83502f444837b3d040a51e8475f15f2\jackson-module-parameter-names-2.19.4.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.fasterxml.jackson.core\jackson-databind\2.19.4\7a39bf9257b726b90b80f27fa3f5174bc75162a5\jackson-databind-2.19.4.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-autoconfigure\3.5.11\3c7d2ec2ac3c301e95814e37fed1c86c19927fc4\spring-boot-autoconfigure-3.5.11.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot\3.5.11\8b7f6df00bfbe74d370e1d05d985a127884d2a9c\spring-boot-3.5.11.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter-logging\3.5.11\62b692ed7aee31a5670796be8b07732b6b836f4e\spring-boot-starter-logging-3.5.11.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\jakarta.annotation\jakarta.annotation-api\2.1.1\48b9bda22b091b1f48b13af03fe36db3be6e1ae3\jakarta.annotation-api-2.1.1.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework\spring-core\6.2.16\a73937f20a303e057add523915b48eb7901e1848\spring-core-6.2.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.yaml\snakeyaml\2.4\e0666b825b796f85521f02360e77f4c92c5a7a07\snakeyaml-2.4.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.apache.tomcat.embed\tomcat-embed-websocket\10.1.52\9d32b801fb474306349013fcdd8317c8cb4d739e\tomcat-embed-websocket-10.1.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.apache.tomcat.embed\tomcat-embed-core\10.1.52\f512bef2796b51299f4752f95918982c3003131d\tomcat-embed-core-10.1.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework\spring-context\6.2.16\caeae6bd50832d6ab28f707aa740e957401a5c20\spring-context-6.2.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework\spring-beans\6.2.16\990289064c810be71630fca9da8e2b6fe8f897b5\spring-beans-6.2.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework\spring-expression\6.2.16\e293ab797b1698084e56ae1f2362b315148683f6\spring-expression-6.2.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.micrometer\micrometer-observation\1.15.9\edf37b25cdfac0704d6fefa4543edb3ed1817eb0\micrometer-observation-1.15.9.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springdoc\springdoc-openapi-starter-common\2.8.16\5b702cb484981b42cfb455bd80b6ce7f49d34210\springdoc-openapi-starter-common-2.8.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.jspecify\jspecify\1.0.0\7425a601c1c7ec76645a78d22b8c6a627edee507\jspecify-1.0.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\jakarta.validation\jakarta.validation-api\3.0.2\92b6631659ba35ca09e44874d3eb936edfeee532\jakarta.validation-api-3.0.2.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.jboss.logging\jboss-logging\3.6.2.Final\3e0a139d7a74cc13b5e01daa8aaa7f71dccd577e\jboss-logging-3.6.2.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.fasterxml\classmate\1.7.3\f61c7e7b81e9249b0f6a05914eff9d54fb09f4a0\classmate-1.7.3.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.zaxxer\HikariCP\6.3.3\7c5aec1e47a97ff40977e0193018865304ea9585\HikariCP-6.3.3.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework\spring-jdbc\6.2.16\addfdde7b3212f34c95d791c37bb04ba4b08a1b7\spring-jdbc-6.2.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\jakarta.persistence\jakarta.persistence-api\3.1.0\66901fa1c373c6aff65c13791cc11da72060a8d6\jakarta.persistence-api-3.1.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\jakarta.transaction\jakarta.transaction-api\2.0.1\51a520e3fae406abb84e2e1148e6746ce3f80a1a\jakarta.transaction-api-2.0.1.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.data\spring-data-commons\3.5.9\6b577c71f563e78a7da984a3d572fde8a4df8103\spring-data-commons-3.5.9.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework\spring-orm\6.2.16\44b3cfb2c046440f83729641c929c405dc7f2c89\spring-orm-6.2.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework\spring-tx\6.2.16\5f9d6e78b76530e6258de8a0dff991fb1ad4b9b0\spring-tx-6.2.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.antlr\antlr4-runtime\4.13.0\5a02e48521624faaf5ff4d99afc88b01686af655\antlr4-runtime-4.13.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.aspectj\aspectjweaver\1.9.25.1\a713c790da4d794c7dfb542b550d4e44898d5e23\aspectjweaver-1.9.25.1.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.security\spring-security-core\6.5.8\d052dca52e49d95d2b03f81ae4b6762eeb4c78d0\spring-security-core-6.5.8.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.projectreactor\reactor-core\3.7.16\dc7f2ba3c4fbc69678937dfe1ad45264d8a1c7be\reactor-core-3.7.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.projectreactor.netty\reactor-netty-http\1.2.15\b20bb13c95b44f1d0c148bdf1197b7d4a7e0f278\reactor-netty-http-1.2.15.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.awspring.cloud\spring-cloud-aws-autoconfigure\3.3.0\b5a0b27e91ee997f8c86e4b0c521858fdcb9dc9b\spring-cloud-aws-autoconfigure-3.3.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.awspring.cloud\spring-cloud-aws-core\3.3.0\3c501426267d8ccbaaebc9796bd5de5bc5d0702e\spring-cloud-aws-core-3.3.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\s3\2.29.52\db65bc6177b0c4514be1f9775cb2094e29e85d3c\s3-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.thymeleaf\thymeleaf\3.1.3.RELEASE\51474f2a90b282ee97dabcd159c7faf24790f373\thymeleaf-3.1.3.RELEASE.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.fasterxml.jackson.core\jackson-core\2.19.4\a720ca9b800742699e041c3890f3731fe516085e\jackson-core-2.19.4.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.fasterxml.jackson.core\jackson-annotations\2.19.4\bbb09b1e7f7f5108890270eb701cb3ddef991c05\jackson-annotations-2.19.4.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\ch.qos.logback\logback-classic\1.5.32\2b1042c50f508f2eb402bd4d22ccbdf94cc37d2e\logback-classic-1.5.32.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.apache.logging.log4j\log4j-to-slf4j\2.24.3\da1143e2a2531ee1c2d90baa98eb50a28a39d5a7\log4j-to-slf4j-2.24.3.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.slf4j\jul-to-slf4j\2.0.17\524cb6ccc2b68a57604750e1ab8b13b5a786a6aa\jul-to-slf4j-2.0.17.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework\spring-jcl\6.2.16\8af6546d28815be574f384dceb93d248e9934f90\spring-jcl-6.2.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.micrometer\micrometer-commons\1.15.9\5a38f43cdc79a309a458c8ce130fff30a2a7f59\micrometer-commons-1.15.9.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.swagger.core.v3\swagger-core-jakarta\2.2.43\500566364be54e3556bcec28922a41ca5fcc7dcd\swagger-core-jakarta-2.2.43.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.security\spring-security-crypto\6.5.8\aec1a6f6c0e06be9dff08b11e8e1f457afca44b2\spring-security-crypto-6.5.8.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.reactivestreams\reactive-streams\1.0.4\3864a1320d97d7b045f729a326e1e077661f31b7\reactive-streams-1.0.4.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.projectreactor.netty\reactor-netty-core\1.2.15\94b2ca82f310c1bf31d3038060e4572eeca1d4b2\reactor-netty-core-1.2.15.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-codec-http2\4.1.131.Final\2e4c47131c60e0bbbca067c891597b466f7033ba\netty-codec-http2-4.1.131.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-codec-http\4.1.131.Final\253d80637ed689ed309ca62371e5fb97746b165\netty-codec-http-4.1.131.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-resolver-dns-native-macos\4.1.131.Final\9e4a908c073e56caa4127f54d946e3e9a5208506\netty-resolver-dns-native-macos-4.1.131.Final-osx-x86_64.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-resolver-dns\4.1.131.Final\7714c0babe26712ccfdbc158aa64898ab909e7d8\netty-resolver-dns-4.1.131.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-transport-native-epoll\4.1.131.Final\10b7a905019c1ad5c37e8cf63d7229fb00668c1d\netty-transport-native-epoll-4.1.131.Final-linux-x86_64.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\aws-core\2.29.52\dcfa86ac727b5d4e0abad1e8b025ac2febb6382e\aws-core-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\auth\2.29.52\76f9b22a99b0de0fd31447db22a5cba4ed4b172e\auth-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\regions\2.29.52\270b31c8695739d495452d380d036c72698e623\regions-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\aws-xml-protocol\2.29.52\e7290d4528affec022bd2f3739853f774a955ac2\aws-xml-protocol-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\protocol-core\2.29.52\1a0e4a114c0943142ca395000a949ee840890fea\protocol-core-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\sdk-core\2.29.52\3f058b489fac3d091417339e02b165e72c637f61\sdk-core-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\arns\2.29.52\879712423589b58434b8831b9b75304a16983178\arns-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\profiles\2.29.52\59dd1368bff2d242d84515ec7ea8fe63bb472c4e\profiles-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\crt-core\2.29.52\6a16e04be0e8bb8a1767e0644c631dadddfdd764\crt-core-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\http-auth\2.29.52\aa4ce3ff7bcd8dcf131a4f5445455b3eb4926dcf\http-auth-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\http-auth-aws\2.29.52\1d0dbfa072bc46207066ffa498ad4ed65c52ac6d\http-auth-aws-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\http-auth-spi\2.29.52\4a64e68a88e3eef0b51819f742931f3607cdd996\http-auth-spi-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\identity-spi\2.29.52\d18449651e8798398cadab6c4b5d8594bb0281c\identity-spi-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\checksums\2.29.52\90631313060ff8ef1ab7745bb1e9740913bdcefc\checksums-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\retries-spi\2.29.52\7e2c7ad44106799491de8cced5925b6473d62e4b\retries-spi-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\http-client-spi\2.29.52\a8da4f289736c702ec6664836761412e7e1e54a2\http-client-spi-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\metrics-spi\2.29.52\92c3797208d24b2b25ab9b6d1bbab624c3af1b9c\metrics-spi-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\json-utils\2.29.52\d88c6c03061b9f3fcd17dc8456365dab67cc1597\json-utils-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\utils\2.29.52\bde94a15cd79b0240bfa10230970e2f0e4c51eba\utils-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\checksums-spi\2.29.52\537363296f035a935b7d3b50a5bef90014d38010\checksums-spi-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\endpoints-spi\2.29.52\bd702a44ad440628af93afa1ec1d7cdc56baec67\endpoints-spi-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\annotations\2.29.52\9fa958ce528b57d90db01c5015daaf7bd373e57f\annotations-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.attoparser\attoparser\2.0.7.RELEASE\e5d0e988d9124139d645bb5872b24dfa23e283cc\attoparser-2.0.7.RELEASE.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.unbescape\unbescape\1.1.6.RELEASE\7b90360afb2b860e09e8347112800d12c12b2a13\unbescape-1.1.6.RELEASE.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\ch.qos.logback\logback-core\1.5.32\fdfb3ff9a842303d4a95207294a6c6bc64e2605d\logback-core-1.5.32.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.apache.logging.log4j\log4j-api\2.24.3\b02c125db8b6d295adf72ae6e71af5d83bce2370\log4j-api-2.24.3.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.swagger.core.v3\swagger-models-jakarta\2.2.43\a68f7470eb763609878460272000f260eabc24dc\swagger-models-jakarta-2.2.43.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.fasterxml.jackson.dataformat\jackson-dataformat-yaml\2.19.4\500956daea0869bf753b94fdaa77e5dc99847d79\jackson-dataformat-yaml-2.19.4.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.apache.commons\commons-lang3\3.17.0\b17d2136f0460dcc0d2016ceefca8723bdf4ee70\commons-lang3-3.17.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.swagger.core.v3\swagger-annotations-jakarta\2.2.43\dbd40253251deabb7a628a54b4550dc4fb492f4\swagger-annotations-jakarta-2.2.43.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\jakarta.xml.bind\jakarta.xml.bind-api\4.0.4\d6d2327f3817d9a33a3b6b8f2e15a96bc2e7afdc\jakarta.xml.bind-api-4.0.4.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-handler-proxy\4.1.131.Final\5ff9e74613a9dd3ca078f06880a16c8cdc046de0\netty-handler-proxy-4.1.131.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-handler\4.1.131.Final\5ca67999f41c0a68f0b66485ceb990683a0b0694\netty-handler-4.1.131.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-codec\4.1.131.Final\1874341f7b29879c6833c17e7305272f0cdc2cb6\netty-codec-4.1.131.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-transport\4.1.131.Final\474862e0855d7a9828fab06a9c73c05387604ee3\netty-transport-4.1.131.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-buffer\4.1.131.Final\f97b636ecd9b81ae3fd1d039b69c4fd3959ecf\netty-buffer-4.1.131.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-common\4.1.131.Final\cdc659109da226b698a74b543a5b97dd0f7e6959\netty-common-4.1.131.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-resolver-dns-classes-macos\4.1.131.Final\b9d57038cc4144e36aee5898085b7f1f018d2c9f\netty-resolver-dns-classes-macos-4.1.131.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-codec-dns\4.1.131.Final\cd23e12e5c3448a1b12c8a4b8deeb4faeb5e483e\netty-codec-dns-4.1.131.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-resolver\4.1.131.Final\9db1bfd7c57b9b6aa9b5cfc61fc3304594bb6b39\netty-resolver-4.1.131.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-transport-classes-epoll\4.1.131.Final\4d7848ac709491fb14f8bce2796fc3eff4a04fd6\netty-transport-classes-epoll-4.1.131.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-transport-native-unix-common\4.1.131.Final\fa975e4751b23d50c0a60569829f31944d11d292\netty-transport-native-unix-common-4.1.131.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\retries\2.29.52\48cb57817dd88977ec71e63550673c5ce010a191\retries-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.eventstream\eventstream\1.0.1\6ff8649dffc5190366ada897ba8525a836297784\eventstream-1.0.1.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\http-auth-aws-eventstream\2.29.52\e8b723c48008bcac96e2cc34c7415bd8b581c601\http-auth-aws-eventstream-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\aws-query-protocol\2.29.52\672d7a2df481414d02eedf3a9eff45fb87f1b8a\aws-query-protocol-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\third-party-jackson-core\2.29.52\82ff600d837e83130502775a1555c45d7a3e2e1\third-party-jackson-core-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\jakarta.activation\jakarta.activation-api\2.1.4\9e5c2a0d75dde71a0bedc4dbdbe47b78a5dc50f8\jakarta.activation-api-2.1.4.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-codec-socks\4.1.131.Final\614eacc17f44d8abaeaea81f210b4980c3568262\netty-codec-socks-4.1.131.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-devtools\3.5.11\fe7dfcaf3153d049909a618a7ba7df288e80f090\spring-boot-devtools-3.5.11.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.jsonwebtoken\jjwt-impl\0.12.6\ac23673a84b6089e0369fb8ab2c69edd91cd6eb0\jjwt-impl-0.12.6.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.jsonwebtoken\jjwt-jackson\0.12.6\f141e0c1136ba17f2632858238a31ae05642dbf8\jjwt-jackson-0.12.6.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.postgresql\postgresql\42.7.10\35100a3f0899551e27af8fed4a3414619a4663b3\postgresql-42.7.10.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.h2database\h2\2.3.232\4fcc05d966ccdb2812ae8b9a718f69226c0cf4e2\h2-2.3.232.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.grpc\grpc-protobuf-lite\1.69.0\91711f27421babf868e424a64426fccb9e8bf6ec\grpc-protobuf-lite-1.69.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.checkerframework\checker-qual\3.52.0\9c17f496846ab1fca8975c6a50ceac0b3bbe63f0\checker-qual-3.52.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.android\annotations\4.1.1.4\a1678ba907bf92691d879fef34e1a187038f9259\annotations-4.1.1.4.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.codehaus.mojo\animal-sniffer-annotations\1.24\aa9ba58d30e0aad7f1808fce9c541ea3760678d8\animal-sniffer-annotations-1.24.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.grpc\grpc-util\1.69.0\1929ab12fce0c610d9d7229b8767f6abb09ebd51\grpc-util-1.69.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.perfmark\perfmark-api\0.27.0\f86f575a41b091786a4b027cd9c0c1d2e3fc1c01\perfmark-api-0.27.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.grpc\grpc-googleapis\1.69.0\1c11a033d96689a4bf3c92fe89b35f5edaef10c2\grpc-googleapis-1.69.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.grpc\grpc-xds\1.69.0\fa1d282a8ba3ae2a5dc0205d2f6a18b5606b5b62\grpc-xds-1.69.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.grpc\grpc-services\1.69.0\bcd917dad2380ee7cf4728da33816ffb9fad6b8b\grpc-services-1.69.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.re2j\re2j\1.7\2949632c1b4acce0d7784f28e3152e9cf3c2ec7a\re2j-1.7.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.hibernate.common\hibernate-commons-annotations\7.0.3.Final\e183c4be8bb41d12e9f19b374e00c34a0a85f439\hibernate-commons-annotations-7.0.3.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.smallrye\jandex\3.2.0\f17ad860f62a08487b9edabde608f8ac55c62fa7\jandex-3.2.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\net.bytebuddy\byte-buddy\1.17.8\af5735f63d00ca47a9375fae5c7471a36331c6ed\byte-buddy-1.17.8.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.glassfish.jaxb\jaxb-runtime\4.0.6\fb95ebb62564657b2fedfe165b859789ef3a8711\jaxb-runtime-4.0.6.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\jakarta.inject\jakarta.inject-api\2.0.1\4c28afe1991a941d7702fe1362c365f0a8641d1e\jakarta.inject-api-2.0.1.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.glassfish.jaxb\jaxb-core\4.0.6\8e61282303777fc98a00cc3affd0560d68748a75\jaxb-core-4.0.6.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\apache-client\2.29.52\b7ce213c946d69ab1807b3f7ecac1ce29ed60485\apache-client-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\netty-nio-client\2.29.52\20fa79ba82d3b290b12cd10ca49f0ff7608a6107\netty-nio-client-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.eclipse.angus\angus-activation\2.0.3\7f80607ea5014fef0b1779e6c33d63a88a45a563\angus-activation-2.0.3.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.glassfish.jaxb\txw2\4.0.6\4f4cd53b5ff9a2c5aa1211f15ed2569c57dfb044\txw2-4.0.6.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.sun.istack\istack-commons-runtime\4.1.2\18ec117c85f3ba0ac65409136afa8e42bc74e739\istack-commons-runtime-4.1.2.jar +Launcher Type: SUN_STANDARD + +[Global flags] + intx CICompilerCount = 12 {product} {ergonomic} + uint ConcGCThreads = 4 {product} {ergonomic} + uint G1ConcRefinementThreads = 14 {product} {ergonomic} + size_t G1HeapRegionSize = 4194304 {product} {ergonomic} + uintx GCDrainStackTargetSize = 64 {product} {ergonomic} + size_t InitialHeapSize = 532676608 {product} {ergonomic} + bool ManagementServer = true {product} {command line} + size_t MarkStackSize = 4194304 {product} {ergonomic} + size_t MaxHeapSize = 8480882688 {product} {ergonomic} + size_t MinHeapDeltaBytes = 4194304 {product} {ergonomic} + size_t MinHeapSize = 8388608 {product} {ergonomic} + uintx NonNMethodCodeHeapSize = 4096 {pd product} {ergonomic} + uintx NonProfiledCodeHeapSize = 0 {pd product} {ergonomic} + bool ProfileInterpreter = false {pd product} {command line} + uintx ProfiledCodeHeapSize = 0 {pd product} {ergonomic} + size_t SoftMaxHeapSize = 8480882688 {manageable} {ergonomic} + intx TieredStopAtLevel = 1 {product} {command line} + bool UseCompressedOops = true {product lp64_product} {ergonomic} + bool UseG1GC = true {product} {ergonomic} + bool UseLargePagesIndividualAllocation = false {pd product} {ergonomic} + +Logging: +Log output configuration: + #0: stdout all=warning uptime,level,tags foldmultilines=false + #1: stderr all=off uptime,level,tags foldmultilines=false + +Release file: + +Environment Variables: +JAVA_HOME=C:\Users\guswn\.jdks\corretto-19.0.2 +CLASSPATH=%JAVA_HOME%\lib +PATH=%JAVA_HOME%\bin;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\WINDOWS\System32\WindowsPowerShell\v1.0\;C:\WINDOWS\System32\OpenSSH\;D:\application\Git\cmd;C:\Program Files\Docker\Docker\resources\bin;D:\application\putty\;C:\Program Files\dotnet\;C:\Program Files\Bandizip\;D:\application\nodejs\;C:\Users\guswn\AppData\Local\Programs\Python\Python312\Scripts\;C:\Users\guswn\AppData\Local\Programs\Python\Python312\;C:\Users\guswn\AppData\Local\Programs\Python\Launcher\;C:\Users\guswn\AppData\Local\Microsoft\WindowsApps;D:\application\Microsoft VS Code\bin;C:\Users\guswn\AppData\Local\JetBrains\Toolbox\scripts;C:\Users\guswn\.local\bin;D:\application\IntelliJ IDEA 2025.3.2\bin;D:\application\JetBrains Gateway 2025.3.2\bin;C:\Users\guswn\AppData\Roaming\npm +USERNAME=guswn +OS=Windows_NT +PROCESSOR_IDENTIFIER=Intel64 Family 6 Model 170 Stepping 4, GenuineIntel +TMP=C:\Users\guswn\AppData\Local\Temp +TEMP=C:\Users\guswn\AppData\Local\Temp + + + + +Periodic native trim disabled + +--------------- S Y S T E M --------------- + +OS: + Windows 11 , 64 bit Build 26100 (10.0.26100.7920) +OS uptime: 16 days 18:33 hours +Hyper-V role detected + +CPU: total 18 (initial active 18) (9 cores per cpu, 2 threads per core) family 6 model 170 stepping 4 microcode 0x1f, cx8, cmov, fxsr, ht, mmx, 3dnowpref, sse, sse2, sse3, ssse3, sse4.1, sse4.2, popcnt, lzcnt, tsc, tscinvbit, avx, avx2, aes, erms, clmul, bmi1, bmi2, adx, sha, fma, vzeroupper, clflush, clflushopt, clwb, hv, serialize, rdtscp, rdpid, fsrm, f16c, cet_ibt, cet_ss +Processor Information for processor 0 + Max Mhz: 1200, Current Mhz: 1200, Mhz Limit: 1200 +Processor Information for processor 1 + Max Mhz: 1200, Current Mhz: 1200, Mhz Limit: 1200 +Processor Information for processor 2 + Max Mhz: 3600, Current Mhz: 700, Mhz Limit: 684 +Processor Information for processor 3 + Max Mhz: 3600, Current Mhz: 700, Mhz Limit: 684 +Processor Information for processor 4 + Max Mhz: 3600, Current Mhz: 700, Mhz Limit: 684 +Processor Information for processor 5 + Max Mhz: 3600, Current Mhz: 700, Mhz Limit: 684 +Processor Information for processor 6 + Max Mhz: 3600, Current Mhz: 700, Mhz Limit: 684 +Processor Information for processor 7 + Max Mhz: 3600, Current Mhz: 700, Mhz Limit: 684 +Processor Information for processor 8 + Max Mhz: 3600, Current Mhz: 700, Mhz Limit: 684 +Processor Information for processor 9 + Max Mhz: 3600, Current Mhz: 700, Mhz Limit: 684 +Processor Information for processor 10 + Max Mhz: 1200, Current Mhz: 1200, Mhz Limit: 1200 +Processor Information for processor 11 + Max Mhz: 1200, Current Mhz: 1200, Mhz Limit: 1200 +Processor Information for processor 12 + Max Mhz: 1200, Current Mhz: 1200, Mhz Limit: 1200 +Processor Information for processor 13 + Max Mhz: 1200, Current Mhz: 1200, Mhz Limit: 1200 +Processor Information for processor 14 + Max Mhz: 1200, Current Mhz: 1200, Mhz Limit: 1200 +Processor Information for processor 15 + Max Mhz: 1200, Current Mhz: 1200, Mhz Limit: 1200 +Processor Information for processor 16 + Max Mhz: 2500, Current Mhz: 700, Mhz Limit: 700 +Processor Information for processor 17 + Max Mhz: 2500, Current Mhz: 700, Mhz Limit: 700 + +Memory: 4k page, system-wide physical 32346M (3826M free) +TotalPageFile size 61970M (AvailPageFile size 310M) +current process WorkingSet (physical memory assigned to process): 13M, peak: 13M +current process commit charge ("private bytes"): 68M, peak: 576M + +vm_info: OpenJDK 64-Bit Server VM (21.0.10+7-LTS) for windows-amd64 JRE (21.0.10+7-LTS), built on 2026-01-15T22:13:46Z by "Administrator" with MS VC++ 17.14 (VS2022) + +END. diff --git a/hs_err_pid192028.log b/hs_err_pid192028.log new file mode 100644 index 00000000..cd8d3a59 --- /dev/null +++ b/hs_err_pid192028.log @@ -0,0 +1,281 @@ +# +# There is insufficient memory for the Java Runtime Environment to continue. +# Native memory allocation (mmap) failed to map 532676608 bytes. Error detail: G1 virtual space +# Possible reasons: +# The system is out of physical RAM or swap space +# This process is running with CompressedOops enabled, and the Java Heap may be blocking the growth of the native heap +# Possible solutions: +# Reduce memory load on the system +# Increase physical memory or swap space +# Check if swap backing store is full +# Decrease Java heap size (-Xmx/-Xms) +# Decrease number of Java threads +# Decrease Java thread stack sizes (-Xss) +# Set larger code cache with -XX:ReservedCodeCacheSize= +# JVM is running with Zero Based Compressed Oops mode in which the Java heap is +# placed in the first 32GB address space. The Java Heap base address is the +# maximum limit for the native heap growth. Please use -XX:HeapBaseMinAddress +# to set the Java Heap base and to place the Java Heap above 32GB virtual address. +# This output file may be truncated or incomplete. +# +# Out of Memory Error (os_windows.cpp:3714), pid=192028, tid=189352 +# +# JRE version: (21.0.10+7) (build ) +# Java VM: OpenJDK 64-Bit Server VM (21.0.10+7-LTS, mixed mode, emulated-client, sharing, tiered, compressed oops, compressed class ptrs, g1 gc, windows-amd64) +# No core dump will be written. Minidumps are not enabled by default on client versions of Windows +# + +--------------- S U M M A R Y ------------ + +Command Line: -XX:TieredStopAtLevel=1 -Dspring.profiles.active=local -Dspring.output.ansi.enabled=always -Dcom.sun.management.jmxremote -Dspring.jmx.enabled=true -Dspring.liveBeansView.mbeanDomain -Dspring.application.admin.enabled=true -Dmanagement.endpoints.jmx.exposure.include=* -javaagent:C:\Users\guswn\AppData\Local\Programs\IntelliJ IDEA\lib\idea_rt.jar=55095 -Dfile.encoding=UTF-8 -Dsun.stdout.encoding=UTF-8 -Dsun.stderr.encoding=UTF-8 com.swyp.picke.PickeApplication + +Host: Intel(R) Core(TM) Ultra 5 125H, 18 cores, 31G, Windows 11 , 64 bit Build 26100 (10.0.26100.7920) +Time: Mon Mar 30 22:58:20 2026 elapsed time: 2.059801 seconds (0d 0h 0m 2s) + +--------------- T H R E A D --------------- + +Current thread (0x0000012fb4ed3030): JavaThread "Unknown thread" [_thread_in_vm, id=189352, stack(0x00000005f8500000,0x00000005f8600000) (1024K)] + +Stack: [0x00000005f8500000,0x00000005f8600000] +Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code) +V [jvm.dll+0x6df2b9] +V [jvm.dll+0x8bbdeb] +V [jvm.dll+0x8be37a] +V [jvm.dll+0x8bea53] +V [jvm.dll+0x28a7a6] +V [jvm.dll+0x6dbc15] +V [jvm.dll+0x6cfbca] +V [jvm.dll+0x364f6e] +V [jvm.dll+0x36ce3b] +V [jvm.dll+0x3be8d9] +V [jvm.dll+0x3beb7b] +V [jvm.dll+0x339137] +V [jvm.dll+0x339c7b] +V [jvm.dll+0x88634e] +V [jvm.dll+0x3cb831] +V [jvm.dll+0x86f25c] +V [jvm.dll+0x45e901] +V [jvm.dll+0x460541] +C [jli.dll+0x52f0] +C [ucrtbase.dll+0x37b0] +C [KERNEL32.DLL+0x2e8d7] +C [ntdll.dll+0x8c48c] + + +--------------- P R O C E S S --------------- + +Threads class SMR info: +_java_thread_list=0x00007ffa227e2208, length=0, elements={ +} + +Java Threads: ( => current thread ) +Total: 0 + +Other Threads: + 0x0000012fcd0203f0 WorkerThread "GC Thread#0" [id=193216, stack(0x00000005f8600000,0x00000005f8700000) (1024K)] + 0x0000012fb7315ca0 ConcurrentGCThread "G1 Main Marker" [id=154308, stack(0x00000005f8700000,0x00000005f8800000) (1024K)] + 0x0000012fb73180e0 WorkerThread "G1 Conc#0" [id=191576, stack(0x00000005f8800000,0x00000005f8900000) (1024K)] + +[error occurred during error reporting (printing all threads), id 0xc0000005, EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x00007ffa21edbbb7] +VM state: not at safepoint (not fully initialized) + +VM Mutex/Monitor currently owned by a thread: ([mutex/lock_event]) +[0x00007ffa228566b0] Heap_lock - owner thread: 0x0000012fb4ed3030 + +Heap address: 0x0000000606800000, size: 8088 MB, Compressed Oops mode: Zero based, Oop shift amount: 3 + +CDS archive(s) mapped at: [0x0000000000000000-0x0000000000000000-0x0000000000000000), size 0, SharedBaseAddress: 0x0000000800000000, ArchiveRelocationMode: 1. +Narrow klass base: 0x0000000000000000, Narrow klass shift: 0, Narrow klass range: 0x0 + +GC Precious Log: + CardTable entry size: 512 + Card Set container configuration: InlinePtr #cards 4 size 8 Array Of Cards #cards 32 size 80 Howl #buckets 8 coarsen threshold 7372 Howl Bitmap #cards 1024 size 144 coarsen threshold 921 Card regions per heap region 1 cards per card region 8192 + +Heap: + garbage-first heap total 0K, used 0K [0x0000000606800000, 0x0000000800000000) + region size 4096K, 0 young (0K), 0 survivors (0K) + +[error occurred during error reporting (printing heap information), id 0xc0000005, EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x00007ffa222c9019] +GC Heap History (0 events): +No events + +Dll operation events (1 events): +Event: 0.044 Loaded shared library D:\application\.jdk\bin\java.dll + +Deoptimization events (0 events): +No events + +Classes loaded (0 events): +No events + +Classes unloaded (0 events): +No events + +Classes redefined (0 events): +No events + +Internal exceptions (0 events): +No events + +ZGC Phase Switch (0 events): +No events + +VM Operations (0 events): +No events + +Memory protections (0 events): +No events + +Nmethod flushes (0 events): +No events + +Events (0 events): +No events + + +Dynamic libraries: +0x00007ff7fbf60000 - 0x00007ff7fbf6e000 D:\application\.jdk\bin\java.exe +0x00007ffb03b00000 - 0x00007ffb03d67000 C:\WINDOWS\SYSTEM32\ntdll.dll +0x00007ffb02ce0000 - 0x00007ffb02da9000 C:\WINDOWS\System32\KERNEL32.DLL +0x00007ffb00fa0000 - 0x00007ffb01391000 C:\WINDOWS\System32\KERNELBASE.dll +0x00007ffb003e0000 - 0x00007ffb0052b000 C:\WINDOWS\System32\ucrtbase.dll +0x00007ffaeab10000 - 0x00007ffaeab2e000 D:\application\.jdk\bin\VCRUNTIME140.dll +0x00007ffae63b0000 - 0x00007ffae63c8000 D:\application\.jdk\bin\jli.dll +0x00007ffb02db0000 - 0x00007ffb02f75000 C:\WINDOWS\System32\USER32.dll +0x00007ffae7290000 - 0x00007ffae7523000 C:\WINDOWS\WinSxS\amd64_microsoft.windows.common-controls_6595b64144ccf1df_6.0.26100.8037_none_3e092faae333b53b\COMCTL32.dll +0x00007ffb015c0000 - 0x00007ffb015e7000 C:\WINDOWS\System32\win32u.dll +0x00007ffb031a0000 - 0x00007ffb03249000 C:\WINDOWS\System32\msvcrt.dll +0x00007ffb02780000 - 0x00007ffb027ab000 C:\WINDOWS\System32\GDI32.dll +0x00007ffb01770000 - 0x00007ffb0189b000 C:\WINDOWS\System32\gdi32full.dll +0x00007ffb005f0000 - 0x00007ffb00693000 C:\WINDOWS\System32\msvcp_win.dll +0x00007ffb03160000 - 0x00007ffb03191000 C:\WINDOWS\System32\IMM32.DLL +0x00007ffaecfa0000 - 0x00007ffaecfac000 D:\application\.jdk\bin\vcruntime140_1.dll +0x00007ffad39c0000 - 0x00007ffad3a49000 D:\application\.jdk\bin\msvcp140.dll +0x00007ffa21b90000 - 0x00007ffa22938000 D:\application\.jdk\bin\server\jvm.dll +0x00007ffb01d30000 - 0x00007ffb01deb000 C:\WINDOWS\System32\ADVAPI32.dll +0x00007ffb03250000 - 0x00007ffb032f7000 C:\WINDOWS\System32\sechost.dll +0x00007ffb024a0000 - 0x00007ffb025b8000 C:\WINDOWS\System32\RPCRT4.dll +0x00007ffb029a0000 - 0x00007ffb02a14000 C:\WINDOWS\System32\WS2_32.dll +0x00007ffb00240000 - 0x00007ffb0029e000 C:\WINDOWS\SYSTEM32\POWRPROF.dll +0x00007ffaec6c0000 - 0x00007ffaec6f5000 C:\WINDOWS\SYSTEM32\WINMM.dll +0x00007ffae7a30000 - 0x00007ffae7a3b000 C:\WINDOWS\SYSTEM32\VERSION.dll +0x00007ffb00220000 - 0x00007ffb00234000 C:\WINDOWS\SYSTEM32\UMPDC.dll +0x00007ffaff170000 - 0x00007ffaff18b000 C:\WINDOWS\SYSTEM32\kernel.appcore.dll +0x00007ffaea260000 - 0x00007ffaea26a000 D:\application\.jdk\bin\jimage.dll +0x00007ffafe4f0000 - 0x00007ffafe732000 C:\WINDOWS\SYSTEM32\DBGHELP.DLL +0x00007ffb01e50000 - 0x00007ffb021d2000 C:\WINDOWS\System32\combase.dll +0x00007ffb02f80000 - 0x00007ffb03057000 C:\WINDOWS\System32\OLEAUT32.dll +0x00007ffada3d0000 - 0x00007ffada40b000 C:\WINDOWS\SYSTEM32\dbgcore.DLL +0x00007ffb013a0000 - 0x00007ffb01445000 C:\WINDOWS\System32\bcryptPrimitives.dll +0x00007ffae63a0000 - 0x00007ffae63b0000 D:\application\.jdk\bin\instrument.dll +0x00007ffae6310000 - 0x00007ffae6331000 D:\application\.jdk\bin\java.dll + +JVMTI agents: +C:\Users\guswn\AppData\Local\Programs\IntelliJ IDEA\lib\idea_rt.jar path:none, loaded, not initialized, instrumentlib options:55095 + +dbghelp: loaded successfully - version: 4.0.5 - missing functions: none +symbol engine: initialized successfully - sym options: 0x614 - pdb path: .;D:\application\.jdk\bin;C:\WINDOWS\SYSTEM32;C:\WINDOWS\WinSxS\amd64_microsoft.windows.common-controls_6595b64144ccf1df_6.0.26100.8037_none_3e092faae333b53b;D:\application\.jdk\bin\server + +VM Arguments: +jvm_args: -XX:TieredStopAtLevel=1 -Dspring.profiles.active=local -Dspring.output.ansi.enabled=always -Dcom.sun.management.jmxremote -Dspring.jmx.enabled=true -Dspring.liveBeansView.mbeanDomain -Dspring.application.admin.enabled=true -Dmanagement.endpoints.jmx.exposure.include=* -javaagent:C:\Users\guswn\AppData\Local\Programs\IntelliJ IDEA\lib\idea_rt.jar=55095 -Dfile.encoding=UTF-8 -Dsun.stdout.encoding=UTF-8 -Dsun.stderr.encoding=UTF-8 +java_command: com.swyp.picke.PickeApplication +java_class_path (initial): D:\Desktop\project\Server\build\classes\java\main;D:\Desktop\project\Server\build\resources\main;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.projectlombok\lombok\1.18.42\8365263844ebb62398e0dc33057ba10ba472d3b8\lombok-1.18.42.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter-web\3.5.11\68fde4c94249e92526105a93ac7c22bd89b6945e\spring-boot-starter-web-3.5.11.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springdoc\springdoc-openapi-starter-webmvc-ui\2.8.16\61c68f705d3f17e8318fb18b2904fa6368af251c\springdoc-openapi-starter-webmvc-ui-2.8.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter-validation\3.5.11\903eefb6eab302617b0f01cc6d65664343bff2a7\spring-boot-starter-validation-3.5.11.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter-data-jpa\3.5.11\f176e5c643720818ec7910e1dd2ccb402411cc5d\spring-boot-starter-data-jpa-3.5.11.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter-security\3.5.11\db8b6b7951883dea3ce7404f20d6816104cedd4e\spring-boot-starter-security-3.5.11.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.jsonwebtoken\jjwt-api\0.12.6\478886a888f6add04937baf0361144504a024967\jjwt-api-0.12.6.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter-webflux\3.5.11\1461f9a6b6b8397ad71a98c9bbf4278159fb9624\spring-boot-starter-webflux-3.5.11.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.crypto.tink\apps-rewardedads\1.9.1\cbaf11457b36fe57d90a5cb16a76833906486503\apps-rewardedads-1.9.1.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.cloud\google-cloud-texttospeech\2.58.0\9be37bd3c81c14c72c9cbcfa2dfaf6dad7a35075\google-cloud-texttospeech-2.58.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.awspring.cloud\spring-cloud-aws-starter-s3\3.3.0\fa9790f990ab540814aafdbf2e97c8cd53b5b1a6\spring-cloud-aws-starter-s3-3.3.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter-thymeleaf\3.5.11\d997aa0df579cf43507d425057940e2712e44808\spring-boot-starter-thymeleaf-3.5.11.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter-json\3.5.11\4cdcd68dcddf0a4c645166e39c3fe448fe2b8e98\spring-boot-starter-json-3.5.11.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter\3.5.11\10ce971300fd56d6be5f1cfe7d27ddfb1ed7158d\spring-boot-starter-3.5.11.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter-tomcat\3.5.11\fb7b96cb61e5fd5700aed96194562e32d166b5ef\spring-boot-starter-tomcat-3.5.11.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework\spring-webmvc\6.2.16\ff2db80406f1459fddd14a8d06d57e0e3ab69465\spring-webmvc-6.2.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework\spring-web\6.2.16\2c4355f1f7e5b8969f696cbc90f25cc22f0f2164\spring-web-6.2.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springdoc\springdoc-openapi-starter-webmvc-api\2.8.16\6e41988d84978e529c01a4cc052b761cd27d5b90\springdoc-openapi-starter-webmvc-api-2.8.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.webjars\swagger-ui\5.32.0\d04c7e3e5b8616813136fa36382a548751775528\swagger-ui-5.32.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.webjars\webjars-locator-lite\1.1.3\217ce590453251b39b72c4a9af3986998f6fdbd9\webjars-locator-lite-1.1.3.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.apache.tomcat.embed\tomcat-embed-el\10.1.52\cd94ce17c5a9937eca365eb494711efa10d49b86\tomcat-embed-el-10.1.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.hibernate.validator\hibernate-validator\8.0.3.Final\4425f554297a1c5ba03a3f30e559a9fd91048cf8\hibernate-validator-8.0.3.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter-jdbc\3.5.11\3ce801963caadf6eb29abd68f5a0fe50c9bfe211\spring-boot-starter-jdbc-3.5.11.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.hibernate.orm\hibernate-core\6.6.42.Final\996e3df4a6c67941b582e4493cb9a39c83198f1e\hibernate-core-6.6.42.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.data\spring-data-jpa\3.5.9\56081dde4f663db74ba000c1f8ab30673058c363\spring-data-jpa-3.5.9.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework\spring-aspects\6.2.16\763140a66821c494985533f29280a3b4132cf055\spring-aspects-6.2.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.security\spring-security-web\6.5.8\3db7bf41191d5b23493cca6252595405b5112b34\spring-security-web-6.5.8.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.security\spring-security-config\6.5.8\302d32eba89131c0ffd15ba0a1e465051336d42f\spring-security-config-6.5.8.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework\spring-aop\6.2.16\59250efa248420a114fe23b4ccf2fea46b804186\spring-aop-6.2.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework\spring-webflux\6.2.16\699ef8bc182893f9ed43206d372f20c4f9aa3231\spring-webflux-6.2.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter-reactor-netty\3.5.11\f98bd3e3019078679dec4f21fb63152aa2e059a7\spring-boot-starter-reactor-netty-3.5.11.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.crypto.tink\tink\1.10.0\84771b1a4bb5726f73fb8490fadb23f1d2aacd38\tink-1.10.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.code.gson\gson\2.13.2\48b8230771e573b54ce6e867a9001e75977fe78e\gson-2.13.2.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.http-client\google-http-client\1.45.3\dde98b597081b98514867c9cefa551fcdea3a28c\google-http-client-1.45.3.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.errorprone\error_prone_annotations\2.41.0\4381275efdef6ddfae38f002c31e84cd001c97f0\error_prone_annotations-2.41.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.opencensus\opencensus-contrib-http-util\0.31.1\3c13fc5715231fadb16a9b74a44d9d59c460cfa8\opencensus-contrib-http-util-0.31.1.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.guava\guava\33.4.0-jre\3fcc0a259f724c7de54a6a55ea7e26d3d5c0cac\guava-33.4.0-jre.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.grpc\grpc-api\1.69.0\965c2c7f708cd6e6ddbf1eb175c3e87e96e41297\grpc-api-1.69.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.code.findbugs\jsr305\3.0.2\25ea2e8b0c338a877313bd4672d3fe056ea78f0d\jsr305-3.0.2.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.grpc\grpc-stub\1.69.0\9e7dc30a9c2df70e25ef4b941f46187e6e178e7a\grpc-stub-1.69.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.grpc\grpc-protobuf\1.69.0\2990b4948357d4fe46aaecb47290cff102079f1e\grpc-protobuf-1.69.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.api\api-common\2.43.0\963d97d95e9bf7275cc26f0b6b72e2aa5b92c6fd\api-common-2.43.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.auto.value\auto-value-annotations\1.11.0\f0d047931d07cfbc6fa4079854f181ff62891d6f\auto-value-annotations-1.11.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\javax.annotation\javax.annotation-api\1.3.2\934c04d3cfef185a8008e7bf34331b79730a9d43\javax.annotation-api-1.3.2.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.j2objc\j2objc-annotations\3.0.0\7399e65dd7e9ff3404f4535b2f017093bdb134c7\j2objc-annotations-3.0.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.protobuf\protobuf-java\3.25.5\5ae5c9ec39930ae9b5a61b32b93288818ec05ec1\protobuf-java-3.25.5.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.api.grpc\proto-google-common-protos\2.51.0\ead75a32e6fd65740b6a69feb658254aeab3fef0\proto-google-common-protos-2.51.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.api.grpc\proto-google-cloud-texttospeech-v1\2.58.0\42f1f29876ddfa2523ebcc41dae801195fd8b3ce\proto-google-cloud-texttospeech-v1-2.58.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.api.grpc\proto-google-cloud-texttospeech-v1beta1\0.147.0\576df432a2c1181deabf21a54fdecc1a32f69f4e\proto-google-cloud-texttospeech-v1beta1-0.147.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.guava\failureaccess\1.0.2\c4a06a64e650562f30b7bf9aaec1bfed43aca12b\failureaccess-1.0.2.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.guava\listenablefuture\9999.0-empty-to-avoid-conflict-with-guava\b421526c5f297295adef1c886e5246c39d4ac629\listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.checkerframework\checker-qual\3.48.4\6b5d69a61012211d581e68699baf3beb1fd382da\checker-qual-3.48.4.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.api\gax\2.60.0\2d277e0795cb69bc14e03be068aa002539e3ef49\gax-2.60.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.auth\google-auth-library-credentials\1.31.0\b9cd5346d3a683d9a8d9786453f2419cc832a97f\google-auth-library-credentials-1.31.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.opencensus\opencensus-api\0.31.1\66a60c7201c2b8b20ce495f0295b32bb0ccbbc57\opencensus-api-0.31.1.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.grpc\grpc-context\1.69.0\cea23878872f76418dcd6df0c6eef0bf27463537\grpc-context-1.69.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.auth\google-auth-library-oauth2-http\1.31.0\df5be46d21b983aab8d0250f19b585a94bdedcde\google-auth-library-oauth2-http-1.31.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.api\gax-grpc\2.60.0\ca4d7dc8c2a85fbdba25ff3449726852e2359ae9\gax-grpc-2.60.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.grpc\grpc-inprocess\1.69.0\8ac4d2e13b48bed9624b8bc485c90f3d28820c93\grpc-inprocess-1.69.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.grpc\grpc-core\1.69.0\7dad3419dfb91a77788afcdf79e0477172784910\grpc-core-1.69.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.grpc\grpc-alts\1.69.0\6d1eac6726fd6fd177666c10fd154823b82272eb\grpc-alts-1.69.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.grpc\grpc-grpclb\1.69.0\d2c9c066693ce94805a503bc47f5b1e76f51541c\grpc-grpclb-1.69.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.conscrypt\conscrypt-openjdk-uber\2.5.2\d858f142ea189c62771c505a6548d8606ac098fe\conscrypt-openjdk-uber-2.5.2.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.grpc\grpc-auth\1.69.0\a75e19b20bb732364bdcc0979e9d7c9baa4e408e\grpc-auth-1.69.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.grpc\grpc-netty-shaded\1.69.0\99aa9789172695a4b09fe2af5f5bd0ab1be4ae85\grpc-netty-shaded-1.69.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.api\gax-httpjson\2.60.0\131d9283925337406e35561ec17bf326a9ecec1a\gax-httpjson-2.60.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.apache.httpcomponents\httpclient\4.5.14\1194890e6f56ec29177673f2f12d0b8e627dec98\httpclient-4.5.14.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\commons-codec\commons-codec\1.18.0\ee45d1cf6ec2cc2b809ff04b4dc7aec858e0df8f\commons-codec-1.18.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.apache.httpcomponents\httpcore\4.4.16\51cf043c87253c9f58b539c9f7e44c8894223850\httpcore-4.4.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.http-client\google-http-client-gson\1.45.3\29eba40245c4a4e5466f8764bd894d6a97c6694f\google-http-client-gson-1.45.3.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.protobuf\protobuf-java-util\3.25.5\38cc5ce479603e36466feda2a9f1dfdb2210ef00\protobuf-java-util-3.25.5.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.threeten\threetenbp\1.7.0\8703e893440e550295aa358281db468625bc9a05\threetenbp-1.7.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.awspring.cloud\spring-cloud-aws-starter\3.3.0\7d82d320cb1851beca3005eab2e484a38bd58a08\spring-cloud-aws-starter-3.3.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.awspring.cloud\spring-cloud-aws-s3\3.3.0\661e2914e3ad6555e20ffa262a9987c15bcc1712\spring-cloud-aws-s3-3.3.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.slf4j\slf4j-api\2.0.17\d9e58ac9c7779ba3bf8142aff6c830617a7fe60f\slf4j-api-2.0.17.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.thymeleaf\thymeleaf-spring6\3.1.3.RELEASE\4b276ea2bd536a18e44b40ff1d9f4848965ff59c\thymeleaf-spring6-3.1.3.RELEASE.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.fasterxml.jackson.datatype\jackson-datatype-jdk8\2.19.4\90d304bcdb1a4bacb6f4347be625d75300973c60\jackson-datatype-jdk8-2.19.4.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.fasterxml.jackson.datatype\jackson-datatype-jsr310\2.19.4\3cbcf2e636a6b062772299bf19a347536e58c4df\jackson-datatype-jsr310-2.19.4.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.fasterxml.jackson.module\jackson-module-parameter-names\2.19.4\502dfea4c83502f444837b3d040a51e8475f15f2\jackson-module-parameter-names-2.19.4.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.fasterxml.jackson.core\jackson-databind\2.19.4\7a39bf9257b726b90b80f27fa3f5174bc75162a5\jackson-databind-2.19.4.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-autoconfigure\3.5.11\3c7d2ec2ac3c301e95814e37fed1c86c19927fc4\spring-boot-autoconfigure-3.5.11.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot\3.5.11\8b7f6df00bfbe74d370e1d05d985a127884d2a9c\spring-boot-3.5.11.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter-logging\3.5.11\62b692ed7aee31a5670796be8b07732b6b836f4e\spring-boot-starter-logging-3.5.11.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\jakarta.annotation\jakarta.annotation-api\2.1.1\48b9bda22b091b1f48b13af03fe36db3be6e1ae3\jakarta.annotation-api-2.1.1.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework\spring-core\6.2.16\a73937f20a303e057add523915b48eb7901e1848\spring-core-6.2.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.yaml\snakeyaml\2.4\e0666b825b796f85521f02360e77f4c92c5a7a07\snakeyaml-2.4.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.apache.tomcat.embed\tomcat-embed-websocket\10.1.52\9d32b801fb474306349013fcdd8317c8cb4d739e\tomcat-embed-websocket-10.1.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.apache.tomcat.embed\tomcat-embed-core\10.1.52\f512bef2796b51299f4752f95918982c3003131d\tomcat-embed-core-10.1.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework\spring-context\6.2.16\caeae6bd50832d6ab28f707aa740e957401a5c20\spring-context-6.2.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework\spring-beans\6.2.16\990289064c810be71630fca9da8e2b6fe8f897b5\spring-beans-6.2.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework\spring-expression\6.2.16\e293ab797b1698084e56ae1f2362b315148683f6\spring-expression-6.2.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.micrometer\micrometer-observation\1.15.9\edf37b25cdfac0704d6fefa4543edb3ed1817eb0\micrometer-observation-1.15.9.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springdoc\springdoc-openapi-starter-common\2.8.16\5b702cb484981b42cfb455bd80b6ce7f49d34210\springdoc-openapi-starter-common-2.8.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.jspecify\jspecify\1.0.0\7425a601c1c7ec76645a78d22b8c6a627edee507\jspecify-1.0.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\jakarta.validation\jakarta.validation-api\3.0.2\92b6631659ba35ca09e44874d3eb936edfeee532\jakarta.validation-api-3.0.2.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.jboss.logging\jboss-logging\3.6.2.Final\3e0a139d7a74cc13b5e01daa8aaa7f71dccd577e\jboss-logging-3.6.2.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.fasterxml\classmate\1.7.3\f61c7e7b81e9249b0f6a05914eff9d54fb09f4a0\classmate-1.7.3.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.zaxxer\HikariCP\6.3.3\7c5aec1e47a97ff40977e0193018865304ea9585\HikariCP-6.3.3.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework\spring-jdbc\6.2.16\addfdde7b3212f34c95d791c37bb04ba4b08a1b7\spring-jdbc-6.2.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\jakarta.persistence\jakarta.persistence-api\3.1.0\66901fa1c373c6aff65c13791cc11da72060a8d6\jakarta.persistence-api-3.1.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\jakarta.transaction\jakarta.transaction-api\2.0.1\51a520e3fae406abb84e2e1148e6746ce3f80a1a\jakarta.transaction-api-2.0.1.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.data\spring-data-commons\3.5.9\6b577c71f563e78a7da984a3d572fde8a4df8103\spring-data-commons-3.5.9.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework\spring-orm\6.2.16\44b3cfb2c046440f83729641c929c405dc7f2c89\spring-orm-6.2.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework\spring-tx\6.2.16\5f9d6e78b76530e6258de8a0dff991fb1ad4b9b0\spring-tx-6.2.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.antlr\antlr4-runtime\4.13.0\5a02e48521624faaf5ff4d99afc88b01686af655\antlr4-runtime-4.13.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.aspectj\aspectjweaver\1.9.25.1\a713c790da4d794c7dfb542b550d4e44898d5e23\aspectjweaver-1.9.25.1.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.security\spring-security-core\6.5.8\d052dca52e49d95d2b03f81ae4b6762eeb4c78d0\spring-security-core-6.5.8.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.projectreactor\reactor-core\3.7.16\dc7f2ba3c4fbc69678937dfe1ad45264d8a1c7be\reactor-core-3.7.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.projectreactor.netty\reactor-netty-http\1.2.15\b20bb13c95b44f1d0c148bdf1197b7d4a7e0f278\reactor-netty-http-1.2.15.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.awspring.cloud\spring-cloud-aws-autoconfigure\3.3.0\b5a0b27e91ee997f8c86e4b0c521858fdcb9dc9b\spring-cloud-aws-autoconfigure-3.3.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.awspring.cloud\spring-cloud-aws-core\3.3.0\3c501426267d8ccbaaebc9796bd5de5bc5d0702e\spring-cloud-aws-core-3.3.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\s3\2.29.52\db65bc6177b0c4514be1f9775cb2094e29e85d3c\s3-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.thymeleaf\thymeleaf\3.1.3.RELEASE\51474f2a90b282ee97dabcd159c7faf24790f373\thymeleaf-3.1.3.RELEASE.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.fasterxml.jackson.core\jackson-core\2.19.4\a720ca9b800742699e041c3890f3731fe516085e\jackson-core-2.19.4.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.fasterxml.jackson.core\jackson-annotations\2.19.4\bbb09b1e7f7f5108890270eb701cb3ddef991c05\jackson-annotations-2.19.4.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\ch.qos.logback\logback-classic\1.5.32\2b1042c50f508f2eb402bd4d22ccbdf94cc37d2e\logback-classic-1.5.32.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.apache.logging.log4j\log4j-to-slf4j\2.24.3\da1143e2a2531ee1c2d90baa98eb50a28a39d5a7\log4j-to-slf4j-2.24.3.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.slf4j\jul-to-slf4j\2.0.17\524cb6ccc2b68a57604750e1ab8b13b5a786a6aa\jul-to-slf4j-2.0.17.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework\spring-jcl\6.2.16\8af6546d28815be574f384dceb93d248e9934f90\spring-jcl-6.2.16.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.micrometer\micrometer-commons\1.15.9\5a38f43cdc79a309a458c8ce130fff30a2a7f59\micrometer-commons-1.15.9.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.swagger.core.v3\swagger-core-jakarta\2.2.43\500566364be54e3556bcec28922a41ca5fcc7dcd\swagger-core-jakarta-2.2.43.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.security\spring-security-crypto\6.5.8\aec1a6f6c0e06be9dff08b11e8e1f457afca44b2\spring-security-crypto-6.5.8.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.reactivestreams\reactive-streams\1.0.4\3864a1320d97d7b045f729a326e1e077661f31b7\reactive-streams-1.0.4.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.projectreactor.netty\reactor-netty-core\1.2.15\94b2ca82f310c1bf31d3038060e4572eeca1d4b2\reactor-netty-core-1.2.15.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-codec-http2\4.1.131.Final\2e4c47131c60e0bbbca067c891597b466f7033ba\netty-codec-http2-4.1.131.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-codec-http\4.1.131.Final\253d80637ed689ed309ca62371e5fb97746b165\netty-codec-http-4.1.131.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-resolver-dns-native-macos\4.1.131.Final\9e4a908c073e56caa4127f54d946e3e9a5208506\netty-resolver-dns-native-macos-4.1.131.Final-osx-x86_64.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-resolver-dns\4.1.131.Final\7714c0babe26712ccfdbc158aa64898ab909e7d8\netty-resolver-dns-4.1.131.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-transport-native-epoll\4.1.131.Final\10b7a905019c1ad5c37e8cf63d7229fb00668c1d\netty-transport-native-epoll-4.1.131.Final-linux-x86_64.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\aws-core\2.29.52\dcfa86ac727b5d4e0abad1e8b025ac2febb6382e\aws-core-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\auth\2.29.52\76f9b22a99b0de0fd31447db22a5cba4ed4b172e\auth-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\regions\2.29.52\270b31c8695739d495452d380d036c72698e623\regions-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\aws-xml-protocol\2.29.52\e7290d4528affec022bd2f3739853f774a955ac2\aws-xml-protocol-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\protocol-core\2.29.52\1a0e4a114c0943142ca395000a949ee840890fea\protocol-core-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\sdk-core\2.29.52\3f058b489fac3d091417339e02b165e72c637f61\sdk-core-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\arns\2.29.52\879712423589b58434b8831b9b75304a16983178\arns-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\profiles\2.29.52\59dd1368bff2d242d84515ec7ea8fe63bb472c4e\profiles-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\crt-core\2.29.52\6a16e04be0e8bb8a1767e0644c631dadddfdd764\crt-core-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\http-auth\2.29.52\aa4ce3ff7bcd8dcf131a4f5445455b3eb4926dcf\http-auth-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\http-auth-aws\2.29.52\1d0dbfa072bc46207066ffa498ad4ed65c52ac6d\http-auth-aws-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\http-auth-spi\2.29.52\4a64e68a88e3eef0b51819f742931f3607cdd996\http-auth-spi-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\identity-spi\2.29.52\d18449651e8798398cadab6c4b5d8594bb0281c\identity-spi-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\checksums\2.29.52\90631313060ff8ef1ab7745bb1e9740913bdcefc\checksums-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\retries-spi\2.29.52\7e2c7ad44106799491de8cced5925b6473d62e4b\retries-spi-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\http-client-spi\2.29.52\a8da4f289736c702ec6664836761412e7e1e54a2\http-client-spi-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\metrics-spi\2.29.52\92c3797208d24b2b25ab9b6d1bbab624c3af1b9c\metrics-spi-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\json-utils\2.29.52\d88c6c03061b9f3fcd17dc8456365dab67cc1597\json-utils-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\utils\2.29.52\bde94a15cd79b0240bfa10230970e2f0e4c51eba\utils-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\checksums-spi\2.29.52\537363296f035a935b7d3b50a5bef90014d38010\checksums-spi-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\endpoints-spi\2.29.52\bd702a44ad440628af93afa1ec1d7cdc56baec67\endpoints-spi-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\annotations\2.29.52\9fa958ce528b57d90db01c5015daaf7bd373e57f\annotations-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.attoparser\attoparser\2.0.7.RELEASE\e5d0e988d9124139d645bb5872b24dfa23e283cc\attoparser-2.0.7.RELEASE.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.unbescape\unbescape\1.1.6.RELEASE\7b90360afb2b860e09e8347112800d12c12b2a13\unbescape-1.1.6.RELEASE.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\ch.qos.logback\logback-core\1.5.32\fdfb3ff9a842303d4a95207294a6c6bc64e2605d\logback-core-1.5.32.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.apache.logging.log4j\log4j-api\2.24.3\b02c125db8b6d295adf72ae6e71af5d83bce2370\log4j-api-2.24.3.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.swagger.core.v3\swagger-models-jakarta\2.2.43\a68f7470eb763609878460272000f260eabc24dc\swagger-models-jakarta-2.2.43.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.fasterxml.jackson.dataformat\jackson-dataformat-yaml\2.19.4\500956daea0869bf753b94fdaa77e5dc99847d79\jackson-dataformat-yaml-2.19.4.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.apache.commons\commons-lang3\3.17.0\b17d2136f0460dcc0d2016ceefca8723bdf4ee70\commons-lang3-3.17.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.swagger.core.v3\swagger-annotations-jakarta\2.2.43\dbd40253251deabb7a628a54b4550dc4fb492f4\swagger-annotations-jakarta-2.2.43.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\jakarta.xml.bind\jakarta.xml.bind-api\4.0.4\d6d2327f3817d9a33a3b6b8f2e15a96bc2e7afdc\jakarta.xml.bind-api-4.0.4.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-handler-proxy\4.1.131.Final\5ff9e74613a9dd3ca078f06880a16c8cdc046de0\netty-handler-proxy-4.1.131.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-handler\4.1.131.Final\5ca67999f41c0a68f0b66485ceb990683a0b0694\netty-handler-4.1.131.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-codec\4.1.131.Final\1874341f7b29879c6833c17e7305272f0cdc2cb6\netty-codec-4.1.131.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-transport\4.1.131.Final\474862e0855d7a9828fab06a9c73c05387604ee3\netty-transport-4.1.131.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-buffer\4.1.131.Final\f97b636ecd9b81ae3fd1d039b69c4fd3959ecf\netty-buffer-4.1.131.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-common\4.1.131.Final\cdc659109da226b698a74b543a5b97dd0f7e6959\netty-common-4.1.131.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-resolver-dns-classes-macos\4.1.131.Final\b9d57038cc4144e36aee5898085b7f1f018d2c9f\netty-resolver-dns-classes-macos-4.1.131.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-codec-dns\4.1.131.Final\cd23e12e5c3448a1b12c8a4b8deeb4faeb5e483e\netty-codec-dns-4.1.131.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-resolver\4.1.131.Final\9db1bfd7c57b9b6aa9b5cfc61fc3304594bb6b39\netty-resolver-4.1.131.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-transport-classes-epoll\4.1.131.Final\4d7848ac709491fb14f8bce2796fc3eff4a04fd6\netty-transport-classes-epoll-4.1.131.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-transport-native-unix-common\4.1.131.Final\fa975e4751b23d50c0a60569829f31944d11d292\netty-transport-native-unix-common-4.1.131.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\retries\2.29.52\48cb57817dd88977ec71e63550673c5ce010a191\retries-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.eventstream\eventstream\1.0.1\6ff8649dffc5190366ada897ba8525a836297784\eventstream-1.0.1.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\http-auth-aws-eventstream\2.29.52\e8b723c48008bcac96e2cc34c7415bd8b581c601\http-auth-aws-eventstream-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\aws-query-protocol\2.29.52\672d7a2df481414d02eedf3a9eff45fb87f1b8a\aws-query-protocol-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\third-party-jackson-core\2.29.52\82ff600d837e83130502775a1555c45d7a3e2e1\third-party-jackson-core-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\jakarta.activation\jakarta.activation-api\2.1.4\9e5c2a0d75dde71a0bedc4dbdbe47b78a5dc50f8\jakarta.activation-api-2.1.4.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.netty\netty-codec-socks\4.1.131.Final\614eacc17f44d8abaeaea81f210b4980c3568262\netty-codec-socks-4.1.131.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-devtools\3.5.11\fe7dfcaf3153d049909a618a7ba7df288e80f090\spring-boot-devtools-3.5.11.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.jsonwebtoken\jjwt-impl\0.12.6\ac23673a84b6089e0369fb8ab2c69edd91cd6eb0\jjwt-impl-0.12.6.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.jsonwebtoken\jjwt-jackson\0.12.6\f141e0c1136ba17f2632858238a31ae05642dbf8\jjwt-jackson-0.12.6.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.postgresql\postgresql\42.7.10\35100a3f0899551e27af8fed4a3414619a4663b3\postgresql-42.7.10.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.h2database\h2\2.3.232\4fcc05d966ccdb2812ae8b9a718f69226c0cf4e2\h2-2.3.232.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.grpc\grpc-protobuf-lite\1.69.0\91711f27421babf868e424a64426fccb9e8bf6ec\grpc-protobuf-lite-1.69.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.checkerframework\checker-qual\3.52.0\9c17f496846ab1fca8975c6a50ceac0b3bbe63f0\checker-qual-3.52.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.android\annotations\4.1.1.4\a1678ba907bf92691d879fef34e1a187038f9259\annotations-4.1.1.4.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.codehaus.mojo\animal-sniffer-annotations\1.24\aa9ba58d30e0aad7f1808fce9c541ea3760678d8\animal-sniffer-annotations-1.24.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.grpc\grpc-util\1.69.0\1929ab12fce0c610d9d7229b8767f6abb09ebd51\grpc-util-1.69.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.perfmark\perfmark-api\0.27.0\f86f575a41b091786a4b027cd9c0c1d2e3fc1c01\perfmark-api-0.27.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.grpc\grpc-googleapis\1.69.0\1c11a033d96689a4bf3c92fe89b35f5edaef10c2\grpc-googleapis-1.69.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.grpc\grpc-xds\1.69.0\fa1d282a8ba3ae2a5dc0205d2f6a18b5606b5b62\grpc-xds-1.69.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.grpc\grpc-services\1.69.0\bcd917dad2380ee7cf4728da33816ffb9fad6b8b\grpc-services-1.69.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.google.re2j\re2j\1.7\2949632c1b4acce0d7784f28e3152e9cf3c2ec7a\re2j-1.7.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.hibernate.common\hibernate-commons-annotations\7.0.3.Final\e183c4be8bb41d12e9f19b374e00c34a0a85f439\hibernate-commons-annotations-7.0.3.Final.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\io.smallrye\jandex\3.2.0\f17ad860f62a08487b9edabde608f8ac55c62fa7\jandex-3.2.0.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\net.bytebuddy\byte-buddy\1.17.8\af5735f63d00ca47a9375fae5c7471a36331c6ed\byte-buddy-1.17.8.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.glassfish.jaxb\jaxb-runtime\4.0.6\fb95ebb62564657b2fedfe165b859789ef3a8711\jaxb-runtime-4.0.6.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\jakarta.inject\jakarta.inject-api\2.0.1\4c28afe1991a941d7702fe1362c365f0a8641d1e\jakarta.inject-api-2.0.1.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.glassfish.jaxb\jaxb-core\4.0.6\8e61282303777fc98a00cc3affd0560d68748a75\jaxb-core-4.0.6.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\apache-client\2.29.52\b7ce213c946d69ab1807b3f7ecac1ce29ed60485\apache-client-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\software.amazon.awssdk\netty-nio-client\2.29.52\20fa79ba82d3b290b12cd10ca49f0ff7608a6107\netty-nio-client-2.29.52.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.eclipse.angus\angus-activation\2.0.3\7f80607ea5014fef0b1779e6c33d63a88a45a563\angus-activation-2.0.3.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\org.glassfish.jaxb\txw2\4.0.6\4f4cd53b5ff9a2c5aa1211f15ed2569c57dfb044\txw2-4.0.6.jar;C:\Users\guswn\.gradle\caches\modules-2\files-2.1\com.sun.istack\istack-commons-runtime\4.1.2\18ec117c85f3ba0ac65409136afa8e42bc74e739\istack-commons-runtime-4.1.2.jar +Launcher Type: SUN_STANDARD + +[Global flags] + intx CICompilerCount = 12 {product} {ergonomic} + uint ConcGCThreads = 4 {product} {ergonomic} + uint G1ConcRefinementThreads = 14 {product} {ergonomic} + size_t G1HeapRegionSize = 4194304 {product} {ergonomic} + uintx GCDrainStackTargetSize = 64 {product} {ergonomic} + size_t InitialHeapSize = 532676608 {product} {ergonomic} + bool ManagementServer = true {product} {command line} + size_t MarkStackSize = 4194304 {product} {ergonomic} + size_t MaxHeapSize = 8480882688 {product} {ergonomic} + size_t MinHeapDeltaBytes = 4194304 {product} {ergonomic} + size_t MinHeapSize = 8388608 {product} {ergonomic} + uintx NonNMethodCodeHeapSize = 4096 {pd product} {ergonomic} + uintx NonProfiledCodeHeapSize = 0 {pd product} {ergonomic} + bool ProfileInterpreter = false {pd product} {command line} + uintx ProfiledCodeHeapSize = 0 {pd product} {ergonomic} + size_t SoftMaxHeapSize = 8480882688 {manageable} {ergonomic} + intx TieredStopAtLevel = 1 {product} {command line} + bool UseCompressedOops = true {product lp64_product} {ergonomic} + bool UseG1GC = true {product} {ergonomic} + bool UseLargePagesIndividualAllocation = false {pd product} {ergonomic} + +Logging: +Log output configuration: + #0: stdout all=warning uptime,level,tags foldmultilines=false + #1: stderr all=off uptime,level,tags foldmultilines=false + +Release file: + +Environment Variables: +JAVA_HOME=C:\Users\guswn\.jdks\corretto-19.0.2 +CLASSPATH=%JAVA_HOME%\lib +PATH=%JAVA_HOME%\bin;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\WINDOWS\System32\WindowsPowerShell\v1.0\;C:\WINDOWS\System32\OpenSSH\;D:\application\Git\cmd;C:\Program Files\Docker\Docker\resources\bin;D:\application\putty\;C:\Program Files\dotnet\;C:\Program Files\Bandizip\;D:\application\nodejs\;C:\Users\guswn\AppData\Local\Programs\Python\Python312\Scripts\;C:\Users\guswn\AppData\Local\Programs\Python\Python312\;C:\Users\guswn\AppData\Local\Programs\Python\Launcher\;C:\Users\guswn\AppData\Local\Microsoft\WindowsApps;D:\application\Microsoft VS Code\bin;C:\Users\guswn\AppData\Local\JetBrains\Toolbox\scripts;C:\Users\guswn\.local\bin;D:\application\IntelliJ IDEA 2025.3.2\bin;D:\application\JetBrains Gateway 2025.3.2\bin;C:\Users\guswn\AppData\Roaming\npm +USERNAME=guswn +OS=Windows_NT +PROCESSOR_IDENTIFIER=Intel64 Family 6 Model 170 Stepping 4, GenuineIntel +TMP=C:\Users\guswn\AppData\Local\Temp +TEMP=C:\Users\guswn\AppData\Local\Temp + + + + +Periodic native trim disabled + +--------------- S Y S T E M --------------- + +OS: + Windows 11 , 64 bit Build 26100 (10.0.26100.7920) +OS uptime: 16 days 18:33 hours +Hyper-V role detected + +CPU: total 18 (initial active 18) (9 cores per cpu, 2 threads per core) family 6 model 170 stepping 4 microcode 0x1f, cx8, cmov, fxsr, ht, mmx, 3dnowpref, sse, sse2, sse3, ssse3, sse4.1, sse4.2, popcnt, lzcnt, tsc, tscinvbit, avx, avx2, aes, erms, clmul, bmi1, bmi2, adx, sha, fma, vzeroupper, clflush, clflushopt, clwb, hv, serialize, rdtscp, rdpid, fsrm, f16c, cet_ibt, cet_ss +Processor Information for processor 0 + Max Mhz: 1200, Current Mhz: 1200, Mhz Limit: 1200 +Processor Information for processor 1 + Max Mhz: 1200, Current Mhz: 1200, Mhz Limit: 1200 +Processor Information for processor 2 + Max Mhz: 3600, Current Mhz: 700, Mhz Limit: 684 +Processor Information for processor 3 + Max Mhz: 3600, Current Mhz: 700, Mhz Limit: 684 +Processor Information for processor 4 + Max Mhz: 3600, Current Mhz: 700, Mhz Limit: 684 +Processor Information for processor 5 + Max Mhz: 3600, Current Mhz: 700, Mhz Limit: 684 +Processor Information for processor 6 + Max Mhz: 3600, Current Mhz: 700, Mhz Limit: 684 +Processor Information for processor 7 + Max Mhz: 3600, Current Mhz: 700, Mhz Limit: 684 +Processor Information for processor 8 + Max Mhz: 3600, Current Mhz: 700, Mhz Limit: 684 +Processor Information for processor 9 + Max Mhz: 3600, Current Mhz: 700, Mhz Limit: 684 +Processor Information for processor 10 + Max Mhz: 1200, Current Mhz: 1200, Mhz Limit: 1200 +Processor Information for processor 11 + Max Mhz: 1200, Current Mhz: 1200, Mhz Limit: 1200 +Processor Information for processor 12 + Max Mhz: 1200, Current Mhz: 1200, Mhz Limit: 1200 +Processor Information for processor 13 + Max Mhz: 1200, Current Mhz: 1200, Mhz Limit: 1200 +Processor Information for processor 14 + Max Mhz: 1200, Current Mhz: 1200, Mhz Limit: 1200 +Processor Information for processor 15 + Max Mhz: 1200, Current Mhz: 1200, Mhz Limit: 1200 +Processor Information for processor 16 + Max Mhz: 2500, Current Mhz: 700, Mhz Limit: 700 +Processor Information for processor 17 + Max Mhz: 2500, Current Mhz: 700, Mhz Limit: 700 + +Memory: 4k page, system-wide physical 32346M (3866M free) +TotalPageFile size 61970M (AvailPageFile size 362M) +current process WorkingSet (physical memory assigned to process): 13M, peak: 13M +current process commit charge ("private bytes"): 68M, peak: 576M + +vm_info: OpenJDK 64-Bit Server VM (21.0.10+7-LTS) for windows-amd64 JRE (21.0.10+7-LTS), built on 2026-01-15T22:13:46Z by "Administrator" with MS VC++ 17.14 (VS2022) + +END. diff --git a/railpack.json b/railpack.json deleted file mode 100644 index 6e969061..00000000 --- a/railpack.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "packages": { - "apt": ["ffmpeg"] - } -} \ No newline at end of file diff --git a/src/main/java/com/swyp/picke/global/infra/media/service/FFmpegService.java b/src/main/java/com/swyp/picke/global/infra/media/service/FFmpegService.java index ac3bc632..6cbd1af5 100644 --- a/src/main/java/com/swyp/picke/global/infra/media/service/FFmpegService.java +++ b/src/main/java/com/swyp/picke/global/infra/media/service/FFmpegService.java @@ -17,49 +17,9 @@ public class FFmpegService implements AudioProcessor { @Value("${media.ffprobe.path:ffprobe}") private String ffprobePath; - private String resolveExecutable(String configuredPath, String fallback) { - if (configuredPath == null || configuredPath.isBlank()) { - return resolveFallbackExecutable(fallback); - } - - File candidate = new File(configuredPath); - if (isAbsolutePath(configuredPath) && !candidate.exists()) { - log.warn("[FFmpeg] 설정된 실행 파일을 찾지 못해 PATH 명령어로 대체합니다: {}", configuredPath); - return resolveFallbackExecutable(fallback); - } - - return configuredPath; - } - - private boolean isAbsolutePath(String path) { - return new File(path).isAbsolute() || path.startsWith("/") || path.startsWith("\\"); - } - - private String resolveFallbackExecutable(String fallback) { - if (File.separatorChar != '\\') { - return fallback; - } - - try { - Process process = new ProcessBuilder("where.exe", fallback).start(); - try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) { - String resolved = reader.readLine(); - process.waitFor(); - if (resolved != null && !resolved.isBlank()) { - return resolved.trim(); - } - } - } catch (Exception e) { - log.debug("[FFmpeg] 대체 실행 파일 탐색 실패: {}, 원인={}", fallback, e.getMessage()); - } - - return fallback; - } - public Integer getAudioDurationMs(File audioFile) throws Exception { - String resolvedFfprobePath = resolveExecutable(ffprobePath, "ffprobe"); String[] cmd = { - resolvedFfprobePath, "-v", "error", "-show_entries", "format=duration", + ffprobePath, "-v", "error", "-show_entries", "format=duration", "-of", "default=noprint_wrappers=1:nokey=1", audioFile.getAbsolutePath() }; Process process = new ProcessBuilder(cmd).start(); @@ -71,12 +31,11 @@ public Integer getAudioDurationMs(File audioFile) throws Exception { } public File createSilenceFile(int durationMs) throws Exception { - String resolvedFfmpegPath = resolveExecutable(ffmpegPath, "ffmpeg"); File output = File.createTempFile("silence_", ".mp3"); double seconds = durationMs / 1000.0; String[] cmd = { - resolvedFfmpegPath, "-y", "-f", "lavfi", "-i", "anullsrc=r=44100:cl=mono", + ffmpegPath, "-y", "-f", "lavfi", "-i", "anullsrc=r=44100:cl=mono", "-t", String.valueOf(seconds), "-acodec", "libmp3lame", output.getAbsolutePath() }; @@ -85,13 +44,15 @@ public File createSilenceFile(int durationMs) throws Exception { } public File mergeAudioFiles(List audioFiles) throws Exception { - if (audioFiles == null || audioFiles.isEmpty()) throw new IllegalArgumentException("merged audio file list is empty."); - String resolvedFfmpegPath = resolveExecutable(ffmpegPath, "ffmpeg"); + if (audioFiles == null || audioFiles.isEmpty()) throw new IllegalArgumentException("병합할 파일이 없습니다."); + // FFmpeg에 전달할 리스트 파일 생성 (UTF-8 인코딩) File listFile = File.createTempFile("ffmpeg_list_", ".txt"); try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(listFile), "UTF-8"))) { for (File file : audioFiles) { + // 윈도우의 'C:\temp\file.mp3'를 'C:/temp/file.mp3'로 변환 String safePath = file.getAbsolutePath().replace("\\", "/"); + // FFmpeg 문법에 맞춰 file '경로' 형태로 기록 writer.write("file '" + safePath + "'"); writer.newLine(); } @@ -99,8 +60,9 @@ public File mergeAudioFiles(List audioFiles) throws Exception { File output = File.createTempFile("merged_full_", ".mp3"); + // 병합 명령어 구성 String[] cmd = { - resolvedFfmpegPath, "-y", "-f", "concat", "-safe", "0", + ffmpegPath, "-y", "-f", "concat", "-safe", "0", "-i", listFile.getAbsolutePath(), "-acodec", "libmp3lame", "-q:a", "2", output.getAbsolutePath() @@ -112,22 +74,24 @@ public File mergeAudioFiles(List audioFiles) throws Exception { } private void executeCommand(String[] cmd) throws Exception { - log.info("[FFmpeg] 명령 실행: {}", String.join(" ", cmd)); + log.info("[FFmpeg] 명령어 실행: {}", String.join(" ", cmd)); ProcessBuilder pb = new ProcessBuilder(cmd); - pb.redirectErrorStream(true); + pb.redirectErrorStream(true); // 에러와 출력을 합침 Process process = pb.start(); + // 실시간 로그 출력 (에러 원인 파악용) try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream(), "UTF-8"))) { String line; while ((line = reader.readLine()) != null) { - log.info("[FFmpeg 출력] {}", line); + log.info("[FFmpeg Output] {}", line); // 문제 발생 시 로그에서 바로 확인 가능 } } int exitCode = process.waitFor(); + if (exitCode != 0) { - log.error("[FFmpeg] 프로세스 오류 발생. Exit Code: {}", exitCode); + log.error("[FFmpeg] 프로세스 오류 발생! Exit Code: {}", exitCode); throw new RuntimeException("FFmpeg 프로세스 오류 발생. Exit Code: " + exitCode); } } -} +} \ No newline at end of file diff --git a/src/test/java/com/swyp/picke/domain/scenario/service/ScenarioAudioPipelineServiceTest.java b/src/test/java/com/swyp/picke/domain/scenario/service/ScenarioAudioPipelineServiceTest.java deleted file mode 100644 index 6e0515e9..00000000 --- a/src/test/java/com/swyp/picke/domain/scenario/service/ScenarioAudioPipelineServiceTest.java +++ /dev/null @@ -1,157 +0,0 @@ -package com.swyp.picke.domain.scenario.service; - -import com.swyp.picke.domain.battle.entity.Battle; -import com.swyp.picke.domain.battle.enums.BattleCreatorType; -import com.swyp.picke.domain.battle.enums.BattleStatus; -import com.swyp.picke.domain.battle.repository.BattleRepository; -import com.swyp.picke.domain.scenario.entity.Scenario; -import com.swyp.picke.domain.scenario.entity.ScenarioNode; -import com.swyp.picke.domain.scenario.entity.Script; -import com.swyp.picke.domain.scenario.enums.AudioPathType; -import com.swyp.picke.domain.scenario.enums.CreatorType; -import com.swyp.picke.domain.scenario.enums.ScenarioStatus; -import com.swyp.picke.domain.scenario.enums.SpeakerType; -import com.swyp.picke.domain.scenario.repository.ScenarioRepository; -import com.swyp.picke.global.infra.media.service.FFmpegService; -import com.swyp.picke.global.infra.s3.service.S3UploadService; -import com.swyp.picke.global.infra.tts.service.TtsService; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; -import org.springframework.test.util.ReflectionTestUtils; - -import java.io.File; -import java.time.LocalDate; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.concurrent.atomic.AtomicInteger; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -@ExtendWith(MockitoExtension.class) -class ScenarioAudioPipelineServiceTest { - - @Mock - private ScenarioRepository scenarioRepository; - - @Mock - private TtsService ttsService; - - @Mock - private S3UploadService s3UploadService; - - @Mock - private BattleRepository battleRepository; - - private FFmpegService ffmpegService; - private ScenarioAudioPipelineService scenarioAudioPipelineService; - private final List uploadedFiles = new ArrayList<>(); - - @BeforeEach - void setUp() { - ffmpegService = new FFmpegService(); - ReflectionTestUtils.setField(ffmpegService, "ffmpegPath", "/usr/bin/ffmpeg"); - ReflectionTestUtils.setField(ffmpegService, "ffprobePath", "/usr/bin/ffprobe"); - - scenarioAudioPipelineService = new ScenarioAudioPipelineService( - scenarioRepository, - ttsService, - ffmpegService, - s3UploadService, - battleRepository - ); - } - - @AfterEach - void tearDown() { - for (File file : uploadedFiles) { - if (file != null && file.exists()) { - file.delete(); - } - } - } - - @Test - void generateAndMergeAudioAsync_usesFallbackExecutableAndCompletesUploadFlow() throws Exception { - Battle battle = Battle.builder() - .title("scenario battle") - .summary("summary") - .description("description") - .targetDate(LocalDate.now()) - .audioDuration(0) - .status(BattleStatus.PENDING) - .creatorType(BattleCreatorType.ADMIN) - .build(); - - Scenario scenario = Scenario.builder() - .battle(battle) - .isInteractive(false) - .status(ScenarioStatus.PENDING) - .creatorType(CreatorType.ADMIN) - .build(); - - ScenarioNode node = ScenarioNode.builder() - .nodeName("START") - .isStartNode(true) - .audioDuration(0) - .build(); - - Script firstScript = Script.builder() - .speakerType(SpeakerType.NARRATOR) - .speakerName("Narrator") - .text("First line") - .build(); - Script secondScript = Script.builder() - .speakerType(SpeakerType.NARRATOR) - .speakerName("Narrator") - .text("Second line") - .build(); - - node.addScript(firstScript); - node.addScript(secondScript); - scenario.addNode(node); - scenario.replaceVoiceSettings(Map.of(SpeakerType.NARRATOR, "voice-narrator")); - - when(scenarioRepository.findById(1L)).thenReturn(Optional.of(scenario)); - when(ttsService.generateTtsWithSsml(eq("First line"), eq(SpeakerType.NARRATOR), eq("voice-narrator"))) - .thenReturn(ffmpegService.createSilenceFile(1000)); - when(ttsService.generateTtsWithSsml(eq("Second line"), eq(SpeakerType.NARRATOR), eq("voice-narrator"))) - .thenReturn(ffmpegService.createSilenceFile(1000)); - - AtomicInteger chunkIndex = new AtomicInteger(); - when(s3UploadService.uploadFile(anyString(), any(File.class))).thenAnswer(invocation -> { - File file = invocation.getArgument(1, File.class); - uploadedFiles.add(file); - - String key = invocation.getArgument(0, String.class); - if (key.contains("/chunks/")) { - return "s3://scenario/chunks/" + chunkIndex.incrementAndGet() + ".mp3"; - } - return "s3://scenario/merged/common.mp3"; - }); - - scenarioAudioPipelineService.generateAndMergeAudioAsync(1L); - - assertThat(scenario.getStatus()).isEqualTo(ScenarioStatus.PUBLISHED); - assertThat(firstScript.getAudioUrl()).isEqualTo("s3://scenario/chunks/1.mp3"); - assertThat(secondScript.getAudioUrl()).isEqualTo("s3://scenario/chunks/2.mp3"); - assertThat(scenario.getAudios()).containsEntry(AudioPathType.COMMON, "s3://scenario/merged/common.mp3"); - assertThat(battle.getAudioDuration()).isNotNull().isGreaterThan(0); - - verify(ttsService, times(2)).generateTtsWithSsml(anyString(), eq(SpeakerType.NARRATOR), eq("voice-narrator")); - verify(s3UploadService, times(3)).uploadFile(anyString(), any(File.class)); - verify(battleRepository).save(battle); - verify(scenarioRepository).saveAndFlush(scenario); - } -}