WebLogic 라이브러리 안정성 검증 로직 강화:
eapim-portal CI / build (push) Has been cancelled
eapim-portal Test / test (push) Has been cancelled

- jboss-logging/Guava 클래스 로드시충돌 점검 추가
- ReadinessController에 관련 체크 로직 반영
This commit is contained in:
Rinjae
2026-08-27 16:47:15 +09:00
parent 2d0ff2bf84
commit 9e32502ee3
@@ -5,6 +5,7 @@ import java.sql.SQLException;
import javax.sql.DataSource;
import org.jboss.logging.Logger;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
@@ -12,19 +13,28 @@ import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.thymeleaf.spring5.SpringTemplateEngine;
import com.google.common.util.concurrent.Futures;
/**
* Readiness probe.
*
* <p>Distinct from {@link HealthCheckController} (liveness — servlet alive?).
* This endpoint validates both EMS and Gateway datasources via JDBC
* {@code Connection.isValid(timeout)}, and the Thymeleaf {@link SpringTemplateEngine}
* configuration, to confirm the app is ready to serve real page requests.
* {@code Connection.isValid(timeout)}, plus three libraries that WebLogic's
* oracle_common bundles at a different version from this app (see weblogic.xml
* {@code prefer-application-packages}): Thymeleaf's {@link SpringTemplateEngine}
* (jackson), jboss-logging, and Guava.
*
* <p>The template-engine check exists because this controller bypasses view
* resolution entirely (plain {@code @RestController} JSON) — a broken
* {@code TemplateEngine.getConfiguration()} (e.g. classpath split causing
* {@link java.util.ServiceConfigurationError} during dialect/module discovery)
* previously left every real page returning 500 while this probe still reported 200.
* <p>These exist because this controller bypasses view resolution entirely
* (plain {@code @RestController} JSON) — a classpath split between the app's
* copy and WebLogic's bundled copy of a preferred package can throw
* {@link LinkageError}/{@link java.util.ServiceConfigurationError} only on the
* real code paths that touch it, while this probe kept reporting 200. That
* already happened once for jackson (Thymeleaf's dialect/module discovery
* failed on every real page while /health/ready stayed green) — jboss-logging
* and Guava carry the same risk (confirmed version mismatch against
* oracle_common, not yet observed failing in production) so they get the same
* kind of forced-touch check here.
*
* <p>HTTP 200 + JSON when all checks pass.
* <p>HTTP 503 + JSON when any check fails — body still includes the per-component
@@ -53,13 +63,18 @@ public class ReadinessController {
String ems = check(portalDataSource);
String gw = check(gatewayDataSource);
String view = checkTemplateEngine();
boolean ok = "UP".equals(ems) && "UP".equals(gw) && "UP".equals(view);
String logging = checkJbossLogging();
String guava = checkGuava();
boolean ok = "UP".equals(ems) && "UP".equals(gw) && "UP".equals(view)
&& "UP".equals(logging) && "UP".equals(guava);
String body = "{"
+ "\"status\":\"" + (ok ? "UP" : "DOWN") + "\","
+ "\"ems\":\"" + ems + "\","
+ "\"gateway\":\"" + gw + "\","
+ "\"view\":\"" + view + "\""
+ "\"view\":\"" + view + "\","
+ "\"logging\":\"" + logging + "\","
+ "\"guava\":\"" + guava + "\""
+ "}";
return ResponseEntity.status(ok ? 200 : 503)
@@ -76,10 +91,39 @@ public class ReadinessController {
templateEngine.getConfiguration();
return "UP";
} catch (Throwable t) {
return down(t);
}
}
/** Forces jboss-logging's {@code Logger} + its bound provider (LogManager/JBoss/JUL
* discovery) to load and actually run a log-level check, not just resolve the class. */
private static String checkJbossLogging() {
try {
Logger log = Logger.getLogger(ReadinessController.class);
log.isDebugEnabled();
return "UP";
} catch (Throwable t) {
return down(t);
}
}
/** {@code Futures.immediateFuture} touches Guava's {@code util.concurrent} machinery
* (AbstractFuture/InternalFutureFailureAccess) — the part backed by the separate
* {@code failureaccess} jar, which is exactly where an app/WebLogic version mismatch
* would split across classloaders. */
private static String checkGuava() {
try {
Futures.immediateFuture(Boolean.TRUE).isDone();
return "UP";
} catch (Throwable t) {
return down(t);
}
}
private static String down(Throwable t) {
String msg = t.getMessage() == null ? t.getClass().getSimpleName() : t.getMessage();
return "DOWN:" + msg.replace('"', '\'').replace('\n', ' ').replace('\r', ' ');
}
}
private static String check(DataSource ds) {
if (ds == null) return "DOWN:NO_DATASOURCE";