@@ -17,13 +17,17 @@ public class AppExceptionHandler {
|
||||
|
||||
@ExceptionHandler(DataAccessException.class)
|
||||
public String handleDataAccessException(DataAccessException exception, Model model) {
|
||||
String detail = exception.getMostSpecificCause() == null
|
||||
? exception.getMessage()
|
||||
: exception.getMostSpecificCause().getMessage();
|
||||
model.addAttribute("errorTitle", "ADB 연결 설정이 필요합니다.");
|
||||
model.addAttribute("errorMessage",
|
||||
"BACKOFFICE_DB_URL, BACKOFFICE_DB_USERNAME, BACKOFFICE_DB_PASSWORD를 실제 ADB 값으로 설정하고 "
|
||||
+ "./run.sh backoffice-support를 실행한 뒤 다시 시도하세요. 상세: " + detail);
|
||||
RuntimeErrorMessage error = RuntimeErrorMessages.dataAccess(exception);
|
||||
model.addAttribute("errorTitle", error.title());
|
||||
model.addAttribute("errorMessage", error.message());
|
||||
return "error";
|
||||
}
|
||||
|
||||
@ExceptionHandler(Exception.class)
|
||||
public String handleUnexpectedException(Exception exception, Model model) {
|
||||
RuntimeErrorMessage error = RuntimeErrorMessages.unexpected(exception);
|
||||
model.addAttribute("errorTitle", error.title());
|
||||
model.addAttribute("errorMessage", error.message());
|
||||
return "error";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,18 +33,14 @@ public class DashboardController {
|
||||
model.addAttribute("roles", permissionService.findRoles());
|
||||
model.addAttribute("tokens", bearerTokenService.findAll());
|
||||
} catch (DataAccessException e) {
|
||||
RuntimeErrorMessage error = RuntimeErrorMessages.dataAccess(e);
|
||||
model.addAttribute("objects", List.of());
|
||||
model.addAttribute("roles", List.of());
|
||||
model.addAttribute("tokens", List.of());
|
||||
model.addAttribute("setupError", dbSetupMessage(e));
|
||||
model.addAttribute("runtimeErrorTitle", error.title());
|
||||
model.addAttribute("runtimeErrorMessage", error.message());
|
||||
model.addAttribute("showSupportCommand", error.showSupportCommand());
|
||||
}
|
||||
return "dashboard";
|
||||
}
|
||||
|
||||
private String dbSetupMessage(DataAccessException e) {
|
||||
String detail = e.getMostSpecificCause() == null ? e.getMessage() : e.getMostSpecificCause().getMessage();
|
||||
return "ADB 연결을 확인할 수 없습니다. BACKOFFICE_DB_URL, BACKOFFICE_DB_USERNAME, "
|
||||
+ "BACKOFFICE_DB_PASSWORD를 설정하고 ./run.sh backoffice-support를 먼저 실행하세요. 상세: "
|
||||
+ detail;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
package com.cloudhandson.vpdbackoffice.web;
|
||||
|
||||
public record RuntimeErrorMessage(
|
||||
String title,
|
||||
String message,
|
||||
boolean showSupportCommand
|
||||
) {
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
package com.cloudhandson.vpdbackoffice.web;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.Locale;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
|
||||
final class RuntimeErrorMessages {
|
||||
|
||||
private RuntimeErrorMessages() {
|
||||
}
|
||||
|
||||
static RuntimeErrorMessage dataAccess(DataAccessException exception) {
|
||||
String detail = detail(exception);
|
||||
if (looksLikeConnectionProblem(exception, detail)) {
|
||||
return new RuntimeErrorMessage(
|
||||
"DB 연결 설정이 필요합니다.",
|
||||
"ADB에 연결할 수 없습니다. BACKOFFICE_DB_URL, BACKOFFICE_DB_USERNAME, "
|
||||
+ "BACKOFFICE_DB_PASSWORD를 확인하고 ./run.sh backoffice-support를 다시 실행하세요. 상세: "
|
||||
+ detail,
|
||||
true
|
||||
);
|
||||
}
|
||||
return new RuntimeErrorMessage(
|
||||
"데이터 처리 오류가 발생했습니다.",
|
||||
"요청을 처리하는 중 DB 데이터 타입, SQL, 또는 매핑 오류가 발생했습니다. "
|
||||
+ "입력값과 백오피스 테이블 스키마를 확인하세요. 상세: " + detail,
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
static RuntimeErrorMessage unexpected(Exception exception) {
|
||||
return new RuntimeErrorMessage(
|
||||
"요청 처리 중 오류가 발생했습니다.",
|
||||
"예상하지 못한 오류가 발생했습니다. 입력값을 확인한 뒤 다시 시도하세요. 상세: "
|
||||
+ safeMessage(exception),
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
private static boolean looksLikeConnectionProblem(DataAccessException exception, String detail) {
|
||||
String text = (exception.getMessage() + " " + detail).toLowerCase(Locale.ROOT);
|
||||
return text.contains("connection refused")
|
||||
|| text.contains("the network adapter could not establish the connection")
|
||||
|| text.contains("io error")
|
||||
|| text.contains("ora-01017")
|
||||
|| text.contains("ora-12154")
|
||||
|| text.contains("ora-12514")
|
||||
|| text.contains("ora-12541");
|
||||
}
|
||||
|
||||
private static String detail(DataAccessException exception) {
|
||||
Throwable cause = exception.getMostSpecificCause();
|
||||
if (cause instanceof SQLException sqlException) {
|
||||
return trim(sqlException.getMessage());
|
||||
}
|
||||
return trim(cause == null ? exception.getMessage() : safeMessage(cause));
|
||||
}
|
||||
|
||||
private static String safeMessage(Throwable throwable) {
|
||||
String message = throwable.getMessage();
|
||||
return trim(message == null || message.isBlank() ? throwable.getClass().getSimpleName() : message);
|
||||
}
|
||||
|
||||
private static String trim(String value) {
|
||||
if (value == null || value.isBlank()) {
|
||||
return "상세 메시지가 없습니다.";
|
||||
}
|
||||
String normalized = value.replaceAll("\\s+", " ").trim();
|
||||
return normalized.length() <= 300 ? normalized : normalized.substring(0, 300) + "...";
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user