From 547ea457372066456c0efc982eb49cd648b0e2fc Mon Sep 17 00:00:00 2001 From: Ryan Miles Date: Thu, 22 Jan 2026 13:49:20 -0800 Subject: [PATCH 1/2] Enhance exception handling to include detailed error message in system error response --- cwms-data-api/src/main/java/cwms/cda/ApiServlet.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cwms-data-api/src/main/java/cwms/cda/ApiServlet.java b/cwms-data-api/src/main/java/cwms/cda/ApiServlet.java index 87c1b1150..2eb6f177a 100644 --- a/cwms-data-api/src/main/java/cwms/cda/ApiServlet.java +++ b/cwms-data-api/src/main/java/cwms/cda/ApiServlet.java @@ -381,7 +381,7 @@ public void init() { ctx.status(HttpServletResponse.SC_BAD_REQUEST).json(re); }) .exception(Exception.class, (e, ctx) -> { - CdaError errResponse = new CdaError("System Error"); + CdaError errResponse = new CdaError("System Error", Map.of("Error message", e.getMessage())); logger.atWarning().withCause(e).log("error on request[%s]: %s", errResponse.getIncidentIdentifier(), ctx.req.getRequestURI()); ctx.status(500); From 1fc2ecf5729113f807adb5ce4274daaf18d05213 Mon Sep 17 00:00:00 2001 From: Ryan Miles Date: Fri, 30 Jan 2026 17:19:37 -0800 Subject: [PATCH 2/2] Sanitizing DataAccessExceptions in the logger. --- .../src/main/java/cwms/cda/ApiServlet.java | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/cwms-data-api/src/main/java/cwms/cda/ApiServlet.java b/cwms-data-api/src/main/java/cwms/cda/ApiServlet.java index 2eb6f177a..ed66c32b3 100644 --- a/cwms-data-api/src/main/java/cwms/cda/ApiServlet.java +++ b/cwms-data-api/src/main/java/cwms/cda/ApiServlet.java @@ -194,6 +194,7 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.sql.SQLException; import java.time.DateTimeException; import java.util.ArrayList; import java.util.Arrays; @@ -212,6 +213,7 @@ import javax.sql.DataSource; import org.apache.http.entity.ContentType; import org.jetbrains.annotations.NotNull; +import org.jooq.exception.DataAccessException; import org.owasp.html.HtmlPolicyBuilder; import org.owasp.html.PolicyFactory; @@ -380,6 +382,15 @@ public void init() { CdaError re = new CdaError(e.getMessage()); ctx.status(HttpServletResponse.SC_BAD_REQUEST).json(re); }) + .exception(DataAccessException.class, (e, ctx) -> { + String message = getSanitizedDataAccessException(e); + CdaError errResponse = new CdaError("System Error", Map.of("Error message", message)); + logger.atWarning().withCause(e).log("error on request[%s]: %s", + errResponse.getIncidentIdentifier(), ctx.req.getRequestURI()); + ctx.status(500); + ctx.contentType(ContentType.APPLICATION_JSON.toString()); + ctx.json(errResponse); + }) .exception(Exception.class, (e, ctx) -> { CdaError errResponse = new CdaError("System Error", Map.of("Error message", e.getMessage())); logger.atWarning().withCause(e).log("error on request[%s]: %s", @@ -400,6 +411,21 @@ public void init() { logger.atInfo().log("Javalin initialized."); } + private static String getSanitizedDataAccessException(DataAccessException e) { + Throwable cause = e.getCause(); + String message = ""; + if (cause instanceof SQLException) { + String localizedMessage = cause.getLocalizedMessage(); + String[] parts = localizedMessage.split("\n"); + message = parts[0]; + int index = message.indexOf(":"); + if (index >= 0) { + message = message.substring(index + 1); + } + } + return message; + } + private String obtainFullVersion(ServletConfig servletConfig) throws ServletException { String relativeWARPath = "/META-INF/MANIFEST.MF"; String absoluteDiskPath = servletConfig.getServletContext().getRealPath(relativeWARPath);