Skip to content

Commit 1922932

Browse files
committed
fix: Address Issue #23 - Resource management for singleton ParentPomResolver
Added JVM shutdown hook to automatically clean up ParentPomResolver resources: - Shutdown hook calls close() on the singleton instance when JVM exits - This ensures repositorySystem.shutdown() is called exactly once - No need for individual MuleApplication instances to close the shared resolver Updated AGENTS.md to document the singleton resource management: - Documented that singleton is automatically cleaned up via shutdown hook - Clarified that application code should NOT call close() on the singleton - Explained when to use new ParentPomResolver() for custom lifecycle Fixed Groovy syntax for shutdown hook (closure syntax works, Java Thread syntax failed): - Changed from 'new Thread({...} as Runnable)' to simple closure 'Runtime.addShutdownHook {...}' All 224 tests pass.
1 parent 54f6528 commit 1922932

2 files changed

Lines changed: 26 additions & 4 deletions

File tree

AGENTS.md

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -176,9 +176,17 @@ Parent POMs are resolved using embedded Maven Resolver (Eclipse Aether):
176176
**Backward Compatibility:**
177177
- Existing methods (`getPomProperty()`, `getDependency()`, `getPlugin()`) still work
178178
- Parent resolution is explicit - call `pomFile.resolveParents(ParentPomResolver.getInstance())` to enable inheritance
179-
- Parent resolution failures are logged as warnings (not fatal)
179+
- `PomFile.resolveParents()` throws `ParentPomResolutionException` on failure (fail-fast)
180+
- `MuleApplication` catches resolution exceptions and logs warnings, allowing rules to operate on raw POM data
180181

181-
**System Properties:**
182+
**Resolver Architecture:**
183+
- `ParentPomResolver.getInstance()` returns a shared singleton instance
184+
- The singleton is initialized lazily on first use (~500ms startup cost)
185+
- A JVM shutdown hook automatically calls `close()` on the singleton to release resources
186+
- Do NOT call `close()` on the singleton instance from application code
187+
- For tests or custom scenarios, use `new ParentPomResolver(path)` and manage lifecycle yourself
188+
189+
**System Properties:
182190
- `mule.linter.localRepo`: Custom local repository path (default: ~/.m2/repository)
183191

184192
**Environment:**

mule-linter-spi/src/main/groovy/com/avioconsulting/mule/linter/resolver/ParentPomResolver.groovy

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,14 @@ class ParentPomResolver {
3939
// Shared instance holder for lazy initialization
4040
private static class Holder {
4141
static final ParentPomResolver INSTANCE = new ParentPomResolver()
42+
43+
static {
44+
// Register shutdown hook to clean up resources when JVM exits
45+
// This ensures repositorySystem.shutdown() is called exactly once
46+
Runtime.addShutdownHook {
47+
INSTANCE.close()
48+
}
49+
}
4250
}
4351

4452
/**
@@ -190,8 +198,14 @@ class ParentPomResolver {
190198

191199
/**
192200
* Shuts down the resolver and cleans up resources.
193-
* Call this when the application is exiting to release HTTP connections,
194-
* thread pools, and other resources held by Maven Resolver.
201+
*
202+
* IMPORTANT: For the singleton instance (getInstance()), this is called
203+
* automatically via JVM shutdown hook. Do NOT call close() on the singleton
204+
* from individual MuleApplication instances.
205+
*
206+
* For manually created instances (new ParentPomResolver()), call this
207+
* when the instance is no longer needed to release HTTP connections,
208+
* thread pools, and other resources.
195209
*/
196210
void close() {
197211
// RepositorySystem manages HTTP clients, thread pools, etc.

0 commit comments

Comments
 (0)