ensure consistent use of context class loader#12579
Conversation
There was a problem hiding this comment.
Pull request overview
Updates service discovery to prefer the thread context class loader (with fallback), improving behavior in environments where services/resources are visible via TCCL rather than the defining class’ loader.
Changes:
- Use TCCL as a fallback when loading
PropertyExpressionResolverimplementations. - Use TCCL (with null fallback) when loading access log
LogElementBuilderimplementations. - Initialize
DefaultBeanIntrospectorwith TCCL (with fallback) to improve introspection reference discovery.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| inject/src/main/java/io/micronaut/context/env/DefaultPropertyPlaceholderResolver.java | Prefer TCCL fallback for loading PropertyExpressionResolver services when environment isn’t an Environment. |
| http-server-netty/src/main/java/io/micronaut/http/server/netty/handler/accesslog/element/AccessLogFormatParser.java | Load LogElementBuilder services using TCCL with fallback to the builder class loader. |
| core/src/main/java/io/micronaut/core/beans/DefaultBeanIntrospector.java | Initialize default introspector’s classloader from TCCL with fallback. |
|
@copilot apply changes based on the comments in this thread |
Agent-Logs-Url: https://github.com/micronaut-projects/micronaut-core/sessions/6bc7e67a-6ab8-4a81-a618-bc6f0fb04aa4 Co-authored-by: graemerocher <66626+graemerocher@users.noreply.github.com>
Applied in e5236a6 — renamed |
…ut-projects/micronaut-core into property-expression-resolver-fix
| exResolvers = new ArrayList<>(DEFAULT_EXPRESSION_RESOLVERS); | ||
| ClassLoader classLoader = (environment instanceof Environment e) ? e.getClassLoader() : environment.getClass().getClassLoader(); | ||
| ClassLoader classLoader = (environment instanceof Environment e) ? e.getClassLoader() : fallbackClassLoader(); | ||
| SoftServiceLoader.load(PropertyExpressionResolver.class, classLoader).collectAll(exResolvers); |
There was a problem hiding this comment.
The class loader selection for PropertyExpressionResolver discovery changed to prefer the thread context class loader when environment is not an Environment. Please add a regression test that sets a custom TCCL with a test PropertyExpressionResolver service entry and verifies it is discovered/used, to prevent future regressions in this class-loader-sensitive behavior.
| ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); | ||
| if (classLoader == null) { | ||
| classLoader = LogElementBuilder.class.getClassLoader(); | ||
| } | ||
| SoftServiceLoader<LogElementBuilder> builders = SoftServiceLoader.load(LogElementBuilder.class, classLoader) | ||
| .disableFork(); |
There was a problem hiding this comment.
Service loading of LogElementBuilder now prefers the thread context class loader in the static initializer. Please add a regression test that sets a custom TCCL with an additional LogElementBuilder via META-INF/services and asserts it is picked up (and also that the fallback works when TCCL is null), since this behavior is class-loader dependent and easy to break inadvertently.
|



If an application is loaded with the alternative context loader there are cases where this context loader is not used. This addresses those cases.