From fa87b444c63c24e74ac9257e7ed4d0c5bb205b6e Mon Sep 17 00:00:00 2001 From: kanguk Date: Wed, 13 Nov 2024 09:40:18 +0900 Subject: [PATCH 1/6] =?UTF-8?q?bug:=20=EC=97=90=EB=9F=AC=20=EB=94=94?= =?UTF-8?q?=EB=B2=84=EA=B9=85=EC=9D=84=20=EC=9C=84=ED=95=B4=20=EB=A1=9C?= =?UTF-8?q?=EA=B9=85=20=ED=9B=84=20=EB=B0=B0=ED=8F=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/cd.yml | 1 + .../scheduler/NotificationScheduler.java | 19 +++++++++++++++++-- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml index 1bc58047..db44dcc4 100644 --- a/.github/workflows/cd.yml +++ b/.github/workflows/cd.yml @@ -5,6 +5,7 @@ on: branches: - develop - 'weekly/**' + - bug/162-bug-push jobs: deploy: diff --git a/src/main/java/com/splanet/splanet/notification/scheduler/NotificationScheduler.java b/src/main/java/com/splanet/splanet/notification/scheduler/NotificationScheduler.java index 9766ddd4..915496ff 100644 --- a/src/main/java/com/splanet/splanet/notification/scheduler/NotificationScheduler.java +++ b/src/main/java/com/splanet/splanet/notification/scheduler/NotificationScheduler.java @@ -13,7 +13,6 @@ import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; - import java.time.LocalDateTime; import java.util.Collections; import java.util.List; @@ -21,6 +20,7 @@ import java.util.Set; import java.util.stream.Collectors; +@Slf4j @Component @RequiredArgsConstructor public class NotificationScheduler { @@ -31,18 +31,21 @@ public class NotificationScheduler { private final NotificationService notificationService; private final QueryPerformanceService queryPerformanceService; - @Scheduled(fixedRate = 60000) public void sendScheduledNotifications() { LocalDateTime now = LocalDateTime.now(); + log.info("Scheduler started at {}", now); List upcomingPlans = planRepository.findUpcomingPlans(now); + log.info("Found {} upcoming plans", upcomingPlans.size()); Set userIds = upcomingPlans.stream() .map(plan -> plan.getUser().getId()) .collect(Collectors.toSet()); + log.info("Collected user IDs: {}", userIds); List allFcmTokens = fcmTokenRepository.findByUserIdIn(userIds); + log.info("Fetched {} FCM tokens", allFcmTokens.size()); Map> userFcmTokenMap = allFcmTokens.stream() .collect(Collectors.groupingBy(fcmToken -> fcmToken.getUser().getId())); @@ -50,12 +53,15 @@ public void sendScheduledNotifications() { Set planIds = upcomingPlans.stream() .map(Plan::getId) .collect(Collectors.toSet()); + log.info("Collected plan IDs: {}", planIds); Set fcmTokenIds = allFcmTokens.stream() .map(FcmToken::getId) .collect(Collectors.toSet()); + log.info("Collected FCM token IDs: {}", fcmTokenIds); List notificationLogs = notificationLogRepository.findByFcmTokenIdInAndPlanIdIn(fcmTokenIds, planIds); + log.info("Found {} notification logs for existing notifications", notificationLogs.size()); Set sentNotificationKeys = notificationLogs.stream() .map(log -> log.getFcmToken().getId() + ":" + log.getPlan().getId()) @@ -64,18 +70,27 @@ public void sendScheduledNotifications() { for (Plan plan : upcomingPlans) { Long userId = plan.getUser().getId(); List fcmTokens = userFcmTokenMap.getOrDefault(userId, Collections.emptyList()); + log.info("Processing plan ID {} for user ID {}, FCM tokens: {}", plan.getId(), userId, fcmTokens.size()); for (FcmToken fcmToken : fcmTokens) { if (Boolean.TRUE.equals(fcmToken.getIsNotificationEnabled())) { LocalDateTime notificationTime = plan.getStartDate().minusMinutes(fcmToken.getNotificationOffset()); + log.info("Evaluating notification for FCM token ID {} at notificationTime: {}", fcmToken.getId(), notificationTime); if (notificationTime.isAfter(now.minusMinutes(5)) && notificationTime.isBefore(now.plusMinutes(1))) { String notificationKey = fcmToken.getId() + ":" + plan.getId(); if (!sentNotificationKeys.contains(notificationKey)) { + log.info("Sending notification for FCM token ID {} and plan ID {}", fcmToken.getId(), plan.getId()); notificationService.sendNotification(fcmToken, plan); + } else { + log.info("Notification already sent for FCM token ID {} and plan ID {}", fcmToken.getId(), plan.getId()); } + } else { + log.info("Notification time {} does not match the required range for now: {}", notificationTime, now); } + } else { + log.info("Notification disabled for FCM token ID {}", fcmToken.getId()); } } } From 33e6318feaf12b3b8f15f9cf68bff5adb74d18a7 Mon Sep 17 00:00:00 2001 From: kanguk Date: Wed, 13 Nov 2024 09:51:30 +0900 Subject: [PATCH 2/6] =?UTF-8?q?bug:=20=EB=B0=B0=ED=8F=AC=20=ED=99=98?= =?UTF-8?q?=EA=B2=BD=EC=97=90=EC=84=9C=20=EC=9E=A1=EB=8B=A4=ED=95=9C=20?= =?UTF-8?q?=EB=A1=9C=EA=B7=B8=EB=8A=94=20=EC=95=88=EB=82=98=EC=98=A4?= =?UTF-8?q?=EA=B2=8C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/splanet/splanet/config/SecurityConfig.java | 1 + src/main/resources/application-local.yml | 5 +++++ src/main/resources/application-prod.yml | 5 +++++ src/main/resources/application.yml | 6 ------ 4 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/splanet/splanet/config/SecurityConfig.java b/src/main/java/com/splanet/splanet/config/SecurityConfig.java index b4f66fdc..ac9357f6 100644 --- a/src/main/java/com/splanet/splanet/config/SecurityConfig.java +++ b/src/main/java/com/splanet/splanet/config/SecurityConfig.java @@ -42,6 +42,7 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Excepti http .csrf(csrf -> csrf.disable()) .authorizeHttpRequests(auth -> auth + .requestMatchers("/error").permitAll() .anyRequest().permitAll() ) .oauth2Login(oauth2 -> oauth2 diff --git a/src/main/resources/application-local.yml b/src/main/resources/application-local.yml index de4b879d..d806ed3d 100644 --- a/src/main/resources/application-local.yml +++ b/src/main/resources/application-local.yml @@ -18,3 +18,8 @@ spring: registration: kakao: redirect-uri: http://localhost:8080/login/oauth2/code/kakao + +logging: + level: + org.springframework.security: TRACE + org.hibernate.engine.internal.StatisticalLoggingSessionEventListener: OFF diff --git a/src/main/resources/application-prod.yml b/src/main/resources/application-prod.yml index 6323a12c..1e013057 100644 --- a/src/main/resources/application-prod.yml +++ b/src/main/resources/application-prod.yml @@ -18,3 +18,8 @@ spring: registration: kakao: redirect-uri: https://api.splanet.co.kr/login/oauth2/code/kakao + +logging: + level: + org.springframework.security: INFO + org.hibernate.engine.internal.StatisticalLoggingSessionEventListener: OFF diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 1b91458c..17f75372 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -34,12 +34,6 @@ spring: scope: profile_nickname, profile_image, account_email client-name: Kakao -logging: - level: - org.springframework.security: TRACE - org.hibernate.engine.internal.StatisticalLoggingSessionEventListener: OFF - - springdoc: swagger-ui: path: /swagger From 4d286321e88aeaa3a1a773368da98768dd7718b6 Mon Sep 17 00:00:00 2001 From: kanguk Date: Wed, 13 Nov 2024 10:01:49 +0900 Subject: [PATCH 3/6] =?UTF-8?q?bug:=20=EB=B0=B0=ED=8F=AC=20=ED=99=98?= =?UTF-8?q?=EA=B2=BD=EC=97=90=EC=84=9C=EC=9D=98=20=EC=8B=9C=EA=B0=84?= =?UTF-8?q?=EB=8C=80=EA=B0=80=20UTC=EB=A1=9C=20=EB=90=98=EC=96=B4=EC=9E=88?= =?UTF-8?q?=EC=96=B4=20=ED=95=9C=EA=B5=AD=20=EC=8B=9C=EA=B0=84=EB=8C=80?= =?UTF-8?q?=EB=A1=9C=20=EB=B0=94=EA=BE=BC=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../notification/scheduler/NotificationScheduler.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/splanet/splanet/notification/scheduler/NotificationScheduler.java b/src/main/java/com/splanet/splanet/notification/scheduler/NotificationScheduler.java index 915496ff..8ffa0e9e 100644 --- a/src/main/java/com/splanet/splanet/notification/scheduler/NotificationScheduler.java +++ b/src/main/java/com/splanet/splanet/notification/scheduler/NotificationScheduler.java @@ -14,6 +14,7 @@ import org.springframework.stereotype.Component; import java.time.LocalDateTime; +import java.time.ZoneId; import java.util.Collections; import java.util.List; import java.util.Map; @@ -31,9 +32,11 @@ public class NotificationScheduler { private final NotificationService notificationService; private final QueryPerformanceService queryPerformanceService; + private static final ZoneId ZONE_ID_SEOUL = ZoneId.of("Asia/Seoul"); + @Scheduled(fixedRate = 60000) public void sendScheduledNotifications() { - LocalDateTime now = LocalDateTime.now(); + LocalDateTime now = LocalDateTime.now(ZONE_ID_SEOUL); log.info("Scheduler started at {}", now); List upcomingPlans = planRepository.findUpcomingPlans(now); @@ -74,7 +77,7 @@ public void sendScheduledNotifications() { for (FcmToken fcmToken : fcmTokens) { if (Boolean.TRUE.equals(fcmToken.getIsNotificationEnabled())) { - LocalDateTime notificationTime = plan.getStartDate().minusMinutes(fcmToken.getNotificationOffset()); + LocalDateTime notificationTime = plan.getStartDate().atZone(ZONE_ID_SEOUL).toLocalDateTime().minusMinutes(fcmToken.getNotificationOffset()); log.info("Evaluating notification for FCM token ID {} at notificationTime: {}", fcmToken.getId(), notificationTime); if (notificationTime.isAfter(now.minusMinutes(5)) && notificationTime.isBefore(now.plusMinutes(1))) { From 892188f295173e8ca63c409c830350e3afc41001 Mon Sep 17 00:00:00 2001 From: kanguk Date: Wed, 13 Nov 2024 10:40:07 +0900 Subject: [PATCH 4/6] =?UTF-8?q?bug:=20=EB=A1=9C=EA=B9=85=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C=20=EB=B0=8F=20=EC=95=8C=EB=A6=BC=20=ED=98=95=EC=8B=9D?= =?UTF-8?q?=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 테스트 알림도 삭제 --- .github/workflows/cd.yml | 1 - .../controller/NotificationController.java | 19 ------- .../scheduler/NotificationScheduler.java | 19 +------ .../service/NotificationService.java | 50 +++++-------------- 4 files changed, 14 insertions(+), 75 deletions(-) delete mode 100644 src/main/java/com/splanet/splanet/notification/controller/NotificationController.java diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml index db44dcc4..1bc58047 100644 --- a/.github/workflows/cd.yml +++ b/.github/workflows/cd.yml @@ -5,7 +5,6 @@ on: branches: - develop - 'weekly/**' - - bug/162-bug-push jobs: deploy: diff --git a/src/main/java/com/splanet/splanet/notification/controller/NotificationController.java b/src/main/java/com/splanet/splanet/notification/controller/NotificationController.java deleted file mode 100644 index 72624a5c..00000000 --- a/src/main/java/com/splanet/splanet/notification/controller/NotificationController.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.splanet.splanet.notification.controller; - -import com.splanet.splanet.notification.service.NotificationService; -import lombok.RequiredArgsConstructor; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.*; - -@RestController -@RequiredArgsConstructor -public class NotificationController implements NotificationApi{ - - private final NotificationService notificationService; - - @Override - public ResponseEntity sendTestNotification(@PathVariable Long userId) { - notificationService.sendTestNotification(userId); - return ResponseEntity.ok("테스트 알림 전송 완료: " + userId); - } -} \ No newline at end of file diff --git a/src/main/java/com/splanet/splanet/notification/scheduler/NotificationScheduler.java b/src/main/java/com/splanet/splanet/notification/scheduler/NotificationScheduler.java index 8ffa0e9e..17fe6dd8 100644 --- a/src/main/java/com/splanet/splanet/notification/scheduler/NotificationScheduler.java +++ b/src/main/java/com/splanet/splanet/notification/scheduler/NotificationScheduler.java @@ -26,29 +26,24 @@ @RequiredArgsConstructor public class NotificationScheduler { + private static final ZoneId ZONE_ID_SEOUL = ZoneId.of("Asia/Seoul"); private final PlanRepository planRepository; private final FcmTokenRepository fcmTokenRepository; private final NotificationLogRepository notificationLogRepository; private final NotificationService notificationService; private final QueryPerformanceService queryPerformanceService; - private static final ZoneId ZONE_ID_SEOUL = ZoneId.of("Asia/Seoul"); - @Scheduled(fixedRate = 60000) public void sendScheduledNotifications() { LocalDateTime now = LocalDateTime.now(ZONE_ID_SEOUL); - log.info("Scheduler started at {}", now); List upcomingPlans = planRepository.findUpcomingPlans(now); - log.info("Found {} upcoming plans", upcomingPlans.size()); Set userIds = upcomingPlans.stream() .map(plan -> plan.getUser().getId()) .collect(Collectors.toSet()); - log.info("Collected user IDs: {}", userIds); List allFcmTokens = fcmTokenRepository.findByUserIdIn(userIds); - log.info("Fetched {} FCM tokens", allFcmTokens.size()); Map> userFcmTokenMap = allFcmTokens.stream() .collect(Collectors.groupingBy(fcmToken -> fcmToken.getUser().getId())); @@ -56,15 +51,12 @@ public void sendScheduledNotifications() { Set planIds = upcomingPlans.stream() .map(Plan::getId) .collect(Collectors.toSet()); - log.info("Collected plan IDs: {}", planIds); Set fcmTokenIds = allFcmTokens.stream() .map(FcmToken::getId) .collect(Collectors.toSet()); - log.info("Collected FCM token IDs: {}", fcmTokenIds); List notificationLogs = notificationLogRepository.findByFcmTokenIdInAndPlanIdIn(fcmTokenIds, planIds); - log.info("Found {} notification logs for existing notifications", notificationLogs.size()); Set sentNotificationKeys = notificationLogs.stream() .map(log -> log.getFcmToken().getId() + ":" + log.getPlan().getId()) @@ -73,27 +65,18 @@ public void sendScheduledNotifications() { for (Plan plan : upcomingPlans) { Long userId = plan.getUser().getId(); List fcmTokens = userFcmTokenMap.getOrDefault(userId, Collections.emptyList()); - log.info("Processing plan ID {} for user ID {}, FCM tokens: {}", plan.getId(), userId, fcmTokens.size()); for (FcmToken fcmToken : fcmTokens) { if (Boolean.TRUE.equals(fcmToken.getIsNotificationEnabled())) { LocalDateTime notificationTime = plan.getStartDate().atZone(ZONE_ID_SEOUL).toLocalDateTime().minusMinutes(fcmToken.getNotificationOffset()); - log.info("Evaluating notification for FCM token ID {} at notificationTime: {}", fcmToken.getId(), notificationTime); if (notificationTime.isAfter(now.minusMinutes(5)) && notificationTime.isBefore(now.plusMinutes(1))) { String notificationKey = fcmToken.getId() + ":" + plan.getId(); if (!sentNotificationKeys.contains(notificationKey)) { - log.info("Sending notification for FCM token ID {} and plan ID {}", fcmToken.getId(), plan.getId()); notificationService.sendNotification(fcmToken, plan); - } else { - log.info("Notification already sent for FCM token ID {} and plan ID {}", fcmToken.getId(), plan.getId()); } - } else { - log.info("Notification time {} does not match the required range for now: {}", notificationTime, now); } - } else { - log.info("Notification disabled for FCM token ID {}", fcmToken.getId()); } } } diff --git a/src/main/java/com/splanet/splanet/notification/service/NotificationService.java b/src/main/java/com/splanet/splanet/notification/service/NotificationService.java index 42167a37..500289ac 100644 --- a/src/main/java/com/splanet/splanet/notification/service/NotificationService.java +++ b/src/main/java/com/splanet/splanet/notification/service/NotificationService.java @@ -12,7 +12,7 @@ import org.springframework.stereotype.Service; import java.time.LocalDateTime; -import java.util.List; +import java.time.format.DateTimeFormatter; @Slf4j @Service @@ -29,53 +29,29 @@ public NotificationService(FcmTokenRepository fcmTokenRepository, FirebaseMessag } public void sendNotification(FcmToken fcmToken, Plan plan) { - String title = "곧 시작하는 플랜: " + plan.getTitle(); - String body = "곧 시작하는 플랜이 있어요! " + plan.getDescription(); + DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("HH시 mm분"); + + String nickname = plan.getUser().getNickname(); + + String startTime = plan.getStartDate().toLocalTime().format(timeFormatter); + String endTime = plan.getEndDate().toLocalTime().format(timeFormatter); + + String title = "🗓️ " + nickname + "님! " + plan.getTitle() + " 시간이에요! "; + String body = startTime + " - " + endTime + " \n" + + (plan.getDescription() != null ? plan.getDescription() : " "); Notification notification = new Notification(title, body); - Message message = Message.builder() - .setToken(fcmToken.getToken()) - .setNotification(notification) - .putData("title", plan.getTitle()) - .putData("title", plan.getDescription()) - .putData("startDate", plan.getStartDate().toString()) - .build(); + Message message = Message.builder().setToken(fcmToken.getToken()).setNotification(notification).putData("title", plan.getTitle()).putData("title", plan.getDescription()).putData("startDate", plan.getStartDate().toString()).build(); try { String response = firebaseMessaging.send(message); log.info("알림을 정상적으로 전송하였습니다. : {}", response); - // 알림 전송 기록 저장 - NotificationLog logEntry = NotificationLog.builder() - .fcmToken(fcmToken) - .plan(plan) - .sentAt(LocalDateTime.now()) - .build(); + NotificationLog logEntry = NotificationLog.builder().fcmToken(fcmToken).plan(plan).sentAt(LocalDateTime.now()).build(); notificationLogRepository.save(logEntry); } catch (Exception e) { log.error("FCM 알림 전송 실패 ", e); } } - - // 알림 테스트를 위한 메소드 (추후 삭제) - public void sendTestNotification(Long userId) { - List fcmTokens = fcmTokenRepository.findByUserId(userId); - - for (FcmToken fcmToken : fcmTokens) { - Notification notification = new Notification("테스트 알림", "이것은 테스트 알림입니다."); - - Message message = Message.builder() - .setToken(fcmToken.getToken()) - .setNotification(notification) - .build(); - - try { - String response = firebaseMessaging.send(message); - log.info("Successfully sent message: {}", response); - } catch (Exception e) { - log.error("Failed to send FCM notification", e); - } - } - } } From 31a329dd1a42674ec147d3527e7f499a62c53798 Mon Sep 17 00:00:00 2001 From: kanguk Date: Wed, 13 Nov 2024 20:08:14 +0900 Subject: [PATCH 5/6] =?UTF-8?q?bug:=20CI=EC=97=90=EC=84=9C=20clean=20build?= =?UTF-8?q?=20=ED=95=98=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 02007b1e..16415da7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -84,7 +84,7 @@ jobs: fi - name: Build with Gradle - run: ./gradlew build -Dspring.profiles.active=test + run: ./gradlew clean build -Dspring.profiles.active=test - name: Run Tests run: ./gradlew test -Dspring.profiles.active=test \ No newline at end of file From 40f00180c176e7564aea37f1fb87e73935cbb8a2 Mon Sep 17 00:00:00 2001 From: kanguk Date: Wed, 13 Nov 2024 20:12:15 +0900 Subject: [PATCH 6/6] =?UTF-8?q?bug:=20=EC=82=AC=EC=9A=A9=ED=95=98=EC=A7=80?= =?UTF-8?q?=20=EC=95=8A=EB=8A=94=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 4 +- .../service/NotificationServiceTest.java | 40 ------------------- 2 files changed, 2 insertions(+), 42 deletions(-) diff --git a/.gitignore b/.gitignore index 3775003e..b502fe8e 100644 --- a/.gitignore +++ b/.gitignore @@ -43,8 +43,8 @@ docker/*.env !docker/sample.env docker/.DS_Store -./splanet.log -./splanet-test.log +splanet.log +splanet-test.log ### log ### logs/ diff --git a/src/test/java/com/splanet/splanet/notification/service/NotificationServiceTest.java b/src/test/java/com/splanet/splanet/notification/service/NotificationServiceTest.java index 195ad673..86e13471 100644 --- a/src/test/java/com/splanet/splanet/notification/service/NotificationServiceTest.java +++ b/src/test/java/com/splanet/splanet/notification/service/NotificationServiceTest.java @@ -87,44 +87,4 @@ void setUp() { e.printStackTrace(); } } - - @Test - void 테스트_알림_전송_성공() { - Long userId = 1L; - FcmToken fcmToken = FcmToken.builder() - .token("FCM토큰") - .build(); - - when(fcmTokenRepository.findByUserId(userId)).thenReturn(List.of(fcmToken)); - try { - when(firebaseMessaging.send(any(Message.class))).thenReturn("응답"); - - assertDoesNotThrow(() -> notificationService.sendTestNotification(userId)); - verify(firebaseMessaging, times(1)).send(any(Message.class)); - verify(fcmTokenRepository, times(1)).findByUserId(userId); - - } catch (Exception e) { - e.printStackTrace(); - } - } - - @Test - void 테스트_알림_전송_실패() { - Long userId = 1L; - FcmToken fcmToken = FcmToken.builder() - .token("FCM토큰") - .build(); - - when(fcmTokenRepository.findByUserId(userId)).thenReturn(Collections.singletonList(fcmToken)); - try { - when(firebaseMessaging.send(any(Message.class))).thenThrow(new RuntimeException("FCM 전송 실패")); - - assertDoesNotThrow(() -> notificationService.sendTestNotification(userId)); - verify(firebaseMessaging, times(1)).send(any(Message.class)); - verify(fcmTokenRepository, times(1)).findByUserId(userId); - - } catch (Exception e) { - e.printStackTrace(); - } - } } \ No newline at end of file