Skip to content

Conversation

@cowwoc
Copy link
Contributor

@cowwoc cowwoc commented Oct 5, 2025

Fixes #375

Problem

Maven 4 auto-injects --module-version ${project.version} to compilerArgs during cache storage but not during validation, causing parameter mismatches and forcing rebuilds on every invocation for modules with module-info.java.

Solution

Add ignorePattern attribute to TrackedProperty that filters array elements using regex before comparison.

Changes

  1. MDO Model (build-cache-config.mdo): Add ignorePattern field to TrackedProperty
  2. Reconciliation Logic (BuildCacheMojosExecutionStrategy.java):
    • filterAndStringifyArray() - filters runtime array values before stringification
    • filterArrayString() - filters cached string representations
    • Apply filtering to both current and expected values before comparison

Configuration Example

<reconcile propertyName="compilerArgs" ignorePattern="--module-version"/>

Testing

Tested with multi-module JPMS project using Maven 4.0.0-rc-4:

  • ✅ No parameter mismatches with --module-version present
  • ✅ Cache correctly reused across builds
  • ✅ Legitimate compilerArgs changes still invalidate cache

Related Issues

Fixes apache#375 - Maven 4 auto-injects --module-version to compilerArgs during
cache storage but not during validation, causing parameter mismatches.

Changes:
- Add ignorePattern field to TrackedProperty in MDO model
- Implement regex-based filtering in BuildCacheMojosExecutionStrategy
- Filter arrays before comparison (both runtime and cached values)

The ignorePattern attribute allows filtering specific array elements
before comparison, solving the Maven 4 module-version problem while
still detecting legitimate compilerArgs changes.

Users can configure this in maven-build-cache-config.xml:
<reconcile propertyName="compilerArgs" ignorePattern="--module-version"/>

Tested with multi-module JPMS project using Maven 4.0.0-rc-4.
@cowwoc
Copy link
Contributor Author

cowwoc commented Oct 5, 2025

This PR addresses #375 by adding an ignorePattern attribute to TrackedProperty that filters out Maven 4's auto-injected --module-version parameter before cache comparison. This prevents false cache invalidation while still detecting legitimate changes to compiler arguments.

@cowwoc
Copy link
Contributor Author

cowwoc commented Oct 5, 2025

@khmarbaise Can you please double-check whether this behavior needs to be fixed in Maven 4? Or do you believe this workaround is the right way to go?

@cowwoc
Copy link
Contributor Author

cowwoc commented Oct 6, 2025

@AlexanderAshitkin I think the first step is to establish whether the problem lies in Maven or this extension. It's not clear to me that Maven 4.0's behavior is correct, given than 3.x does not exhibit this problem.

Is this something you can dig into in the mailing list?

cowwoc pushed a commit to cowwoc/maven-build-cache-extension that referenced this pull request Oct 6, 2025
Implemented all suggestions from @AlexanderAshitkin:

1. **Extracted filtering logic to utility class**
   - Created ArrayFilterUtils with pattern caching
   - Removed inline filtering methods from BuildCacheMojosExecutionStrategy

2. **Changed pattern matching from find() to matches()**
   - Ensures exact pattern matching (e.g., "\d+" matches "123" but not "Maven4")
   - Addresses reviewer's concern about unexpected substring matches

3. **Added pattern caching**
   - Uses ConcurrentHashMap to cache compiled patterns
   - Improves performance for repeated pattern usage

4. **Renamed variable to excludePattern**
   - More descriptive than generic "pattern"

5. **Removed filterArrayString() method**
   - Simplified approach: only filter current values, not cached values
   - When ignore pattern changes, cache rebuilds naturally

6. **Added proper imports**
   - Eliminated fully qualified names (FQNs)
   - All imports are at the top of the file

7. **Comprehensive unit tests**
   - 13 test cases covering all scenarios
   - Tests verify matches() vs find() behavior
   - Tests validate pattern caching
   - All 87 tests pass (existing + new)
cowwoc added a commit to cowwoc/maven-build-cache-extension that referenced this pull request Oct 6, 2025
Implemented all suggestions from @AlexanderAshitkin:

1. **Extracted filtering logic to utility class**
   - Created ArrayFilterUtils with pattern caching
   - Removed inline filtering methods from BuildCacheMojosExecutionStrategy

2. **Changed pattern matching from find() to matches()**
   - Ensures exact pattern matching (e.g., "\d+" matches "123" but not "Maven4")
   - Addresses reviewer's concern about unexpected substring matches

3. **Added pattern caching**
   - Uses ConcurrentHashMap to cache compiled patterns
   - Improves performance for repeated pattern usage

4. **Renamed variable to excludePattern**
   - More descriptive than generic "pattern"

5. **Removed filterArrayString() method**
   - Simplified approach: only filter current values, not cached values
   - When ignore pattern changes, cache rebuilds naturally

6. **Added proper imports**
   - Eliminated fully qualified names (FQNs)
   - All imports are at the top of the file

7. **Comprehensive unit tests**
   - 13 test cases covering all scenarios
   - Tests verify matches() vs find() behavior
   - Tests validate pattern caching
   - All 87 tests pass (existing + new)
@cowwoc cowwoc force-pushed the fix-module-version-filtering-from-master branch from 0c4074b to 4438f43 Compare October 6, 2025 21:49
Implemented all suggestions from @AlexanderAshitkin:

1. **Extracted filtering logic to utility class**
   - Created ArrayFilterUtils with pattern caching
   - Removed inline filtering methods from BuildCacheMojosExecutionStrategy

2. **Changed pattern matching from find() to matches()**
   - Ensures exact pattern matching (e.g., "\d+" matches "123" but not "Maven4")
   - Addresses reviewer's concern about unexpected substring matches

3. **Added pattern caching**
   - Uses ConcurrentHashMap to cache compiled patterns
   - Improves performance for repeated pattern usage

4. **Renamed variable to excludePattern**
   - More descriptive than generic "pattern"

5. **Removed filterArrayString() method**
   - Simplified approach: only filter current values, not cached values
   - When ignore pattern changes, cache rebuilds naturally

6. **Added proper imports**
   - Eliminated fully qualified names (FQNs)
   - All imports are at the top of the file

7. **Comprehensive unit tests**
   - 13 test cases covering all scenarios
   - Tests verify matches() vs find() behavior
   - Tests validate pattern caching
   - All 87 tests pass (existing + new)
@cowwoc cowwoc force-pushed the fix-module-version-filtering-from-master branch from 4438f43 to bb010f6 Compare October 6, 2025 21:50
cowwoc added a commit to cowwoc/maven-build-cache-extension that referenced this pull request Oct 12, 2025
…nate timing mismatch

Maven 4 automatically injects --module-version into compiler arguments during
execution, but cache validation happens before execution. This creates a timing
mismatch that causes cache invalidation.

This fix captures properties at validation time for ALL builds, ensuring
consistent reading at the same lifecycle point.

Changes:
- Modified CacheResult to store validation-time mojo events
- Added captureValidationTimeProperties() method to BuildCacheMojosExecutionStrategy
- Modified execute() to capture properties after findCachedBuild()
- Modified save() to use validation-time events instead of execution-time events
- Added comprehensive integration tests (Maven4Jpms, ExplicitModuleVersion, NonJpms, MultiModule)
- Added implementation documentation

This approach eliminates the need for ignorePattern configuration and fixes
the root cause rather than treating the symptom.

Alternative to PR apache#391
@cowwoc
Copy link
Contributor Author

cowwoc commented Oct 12, 2025

Actually, I think we can do better than this... Please take a look at #395

I suggest closing this PR and going with the new approach instead.

cowwoc added a commit to cowwoc/maven-build-cache-extension that referenced this pull request Oct 12, 2025
…nate timing mismatch

Maven 4 automatically injects --module-version into compiler arguments during
execution, but cache validation happens before execution. This creates a timing
mismatch that causes cache invalidation.

This fix captures properties at validation time for ALL builds, ensuring
consistent reading at the same lifecycle point.

Changes:
- Modified CacheResult to store validation-time mojo events
- Added captureValidationTimeProperties() method to BuildCacheMojosExecutionStrategy
- Modified execute() to capture properties after findCachedBuild()
- Modified save() to use validation-time events instead of execution-time events
- Added comprehensive integration tests (Maven4Jpms, ExplicitModuleVersion, NonJpms, MultiModule)
- Added implementation documentation

This approach eliminates the need for ignorePattern configuration and fixes
the root cause rather than treating the symptom.

Alternative to PR apache#391
cowwoc added a commit to cowwoc/maven-build-cache-extension that referenced this pull request Oct 12, 2025
…nate timing mismatch

Maven 4 automatically injects --module-version into compiler arguments during
execution, but cache validation happens before execution. This creates a timing
mismatch that causes cache invalidation.

This fix captures properties at validation time for ALL builds, ensuring
consistent reading at the same lifecycle point.

Changes:
- Modified CacheResult to store validation-time mojo events
- Added captureValidationTimeProperties() method to BuildCacheMojosExecutionStrategy
- Modified execute() to capture properties after findCachedBuild()
- Modified save() to use validation-time events instead of execution-time events
- Added comprehensive integration tests (Maven4Jpms, ExplicitModuleVersion, NonJpms, MultiModule)
- Added implementation documentation

This approach eliminates the need for ignorePattern configuration and fixes
the root cause rather than treating the symptom.

Alternative to PR apache#391
cowwoc added a commit to cowwoc/maven-build-cache-extension that referenced this pull request Oct 12, 2025
…nate timing mismatch

Maven 4 automatically injects --module-version into compiler arguments during
execution, but cache validation happens before execution. This creates a timing
mismatch that causes cache invalidation.

This fix captures properties at validation time for ALL builds and stores ONLY
validation-time values in the cache, ensuring consistent reading at the same
lifecycle point.

Changes:
- Modified CacheResult to store validation-time mojo events
- Added captureValidationTimeProperties() to BuildCacheMojosExecutionStrategy
- Modified execute() to capture properties after findCachedBuild()
- Modified save() to store ONLY validation-time events (AssertionError if missing)
- Added comprehensive integration tests (Maven4Jpms, ExplicitModuleVersion, NonJpms, MultiModule)

Benefits:
- No configuration required (vs ignorePattern in PR apache#391)
- Fixes root cause (timing mismatch) not symptom (value mismatch)
- Works for ALL Maven 4 auto-injected properties
- Preserves execution-time logging for debugging

Alternative to PR apache#391
@elharo
Copy link
Contributor

elharo commented Oct 28, 2025

Closing per @cowwoc suggestion

@elharo elharo closed this Oct 28, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

3 participants