codeconsole commented on code in PR #15666:
URL: https://github.com/apache/grails-core/pull/15666#discussion_r3611351096
##########
grails-core/src/main/groovy/grails/util/GrailsUtil.java:
##########
@@ -36,11 +41,51 @@ public class GrailsUtil {
private static final Log LOG = LogFactory.getLog(GrailsUtil.class);
private static final boolean LOG_DEPRECATED =
Boolean.valueOf(System.getProperty("grails.log.deprecated",
String.valueOf(Environment.isDevelopmentMode())));
- private static final StackTraceFilterer stackFilterer = new
DefaultStackTraceFilterer();
+
+ /**
+ * Default filterer used before {@link
#initializeStackFilterer(GrailsApplication)} runs (CLI,
+ * tests that don't boot a context, plain {@code main()} usage). Preserves
the pre-PR behaviour
+ * of a single hardcoded {@link DefaultStackTraceFilterer} instance for
the JVM lifetime when no
+ * application is wired.
+ */
+ private static final StackTraceFilterer FALLBACK_FILTERER = new
DefaultStackTraceFilterer();
+
+ /**
+ * Active filterer for {@link #printSanitizedStackTrace}, {@link
#sanitizeRootCause} and
+ * {@link #deepSanitize}. Starts as {@link #FALLBACK_FILTERER} and is
replaced with a
+ * config-driven instance when {@link
#initializeStackFilterer(GrailsApplication)} runs during
+ * Grails bootstrap. Volatile so the bootstrap-time write publishes safely
to the request
+ * threads that read it later.
+ */
+ private static volatile StackTraceFilterer stackFilterer =
FALLBACK_FILTERER;
private GrailsUtil() {
}
+ /**
+ * Installs a {@link StackTraceFilterer} resolved from the given
application's config, replacing
+ * the default fallback. Reads {@link
Settings#SETTING_LOGGING_STACKTRACE_FILTER_CLASS} for the
+ * filterer class and propagates {@link
Settings#SETTING_LOG_FULL_STACKTRACE_ON_FILTER} to
+ * instances of {@link DefaultStackTraceFilterer}. Called by {@code
GrailsExceptionResolver}
+ * during Spring bean wiring (which is the same point the resolver
consults these keys for its
+ * own filterer), so request-time callers of the static {@code
sanitize}/{@code deepSanitize}
+ * methods see the configured instance.
+ *
+ * <p>No-ops when {@code application} is null. Safe to call more than once
— the last successful
+ * invocation wins.
+ *
+ * @since 7.1.5
+ */
+ public static void initializeStackFilterer(GrailsApplication application) {
Review Comment:
Went with a variant of your second option:
GrailsUtil.initializeStackFilterer now takes the already-resolved
StackTraceFilterer instance rather than an Environment, so GrailsUtil has zero
dependency on Spring/Grails config types at all --
GrailsBootstrapRegistryInitializer does the resolution and hands over a ready
instance. One thing worth flagging: environment.getProperty(key, Class.class,
default) won't actually do the String->Class conversion -- neither Spring's
DefaultConversionService nor Boot's ApplicationConversionService register a
String-to-Class converter (checked both jars), so that call throws
ConverterNotFoundException for a real class name. The resolver in
GrailsBootstrapRegistryInitializer reads the property as a String and resolves
it via ClassUtils.forName instead.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]