Merged
Conversation
Replace manual JAR creation with maven-jar-plugin for cleaner Maven integration for three examples. This eliminates shell-based JAR packaging and follows standard Maven conventions. Changes: * Migration approach (Phase 2): - Use maven-jar-plugin to create module-specific JARs - JARs created in target/ directory (not mlib/) - Simplified compile.sh: just 'mvn clean package' - Updated run.sh: use '--module-path target' - Removed mlib/ from .gitignore and clean.sh * Examples migrated: - example_requires_exports (3 modules) - example_annotations (3 modules) - example_hiddenmain (1 module) * Documentation: - Added Phase 2 approach to maven-4-migration.md - Documented maven-jar-plugin configuration pattern - Added migration guide from Phase 1 to Phase 2 - Added step to update documentation (remove mlib references) - Updated directory layout to clarify Phase 1 vs Phase 2 - Listed reference examples for both phases Benefits: - Simpler build scripts (no manual JAR loops) - Standard Maven artifact location (target/) - Easier to maintain (more declarative, less scripting) - JAR naming follows Maven conventions All migrated examples pass golden master verification. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> Introduced in the course of support-and-care/maven-support-and-care#137
Migrate three examples to use maven-jar-plugin (Phase 2): - example_requires_exports-to (4 modules) - example_derived_private-package-protected (2 modules) - example_jerrymouse (1 module) These migrations were required because example_jerrymouse depends on the other two examples and copies their JARs at runtime. Changes: - Replace manual JAR creation with maven-jar-plugin in pom.xml - Update compile.sh to use 'mvn clean package' instead of 'compile' - Update run.sh scripts to use target/ instead of mlib/ for module-path - Remove mlib/ from .gitignore and clean.sh Jerrymouse-specific changes: - Fix apps_copyallexamples2appdir.sh to copy from target/ directory - Fix shellcheck warning: use compgen instead of -e with glob pattern (compgen -G tests if glob matches files, unlike -e which fails with globs) - Update README.adoc to document Phase 2 JAR location (target/) All examples verified with golden master tests. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> Introduced in the course of support-and-care/maven-support-and-care#137
Migrate 32 examples to use maven-jar-plugin for JAR creation instead
of manual jar commands in compile.sh scripts.
Key changes:
Phase 2 JAR Creation (26 examples with pom.xml updates):
- Add maven-jar-plugin configuration with classifier-based executions
- Skip default JAR creation, create module-specific JARs with classifiers
- Results in JARs like: ${artifactId}-${version}-${classifier}.jar
- Remove manual jar commands from compile.sh scripts
- Update run.sh scripts to use --module-path target
- Remove mlib/ directory cleanup from clean.sh scripts
- Remove mlib/ from .gitignore (JARs now in target/ only)
Special Cases - Dynamic Module Loading (4 examples):
Add committed mlib→target symlinks for compatibility with ModuleLayer API:
- example_patch/m4/mlib
- example_layer-hierarchy/m4/mlib
- example_layer-modules-grouped-in-hierarchy/m4/mlib
- example_layer-modules-module-resolution/m4/mlib
These symlinks enable:
- Running from IDE without executing compile.sh
- Compatibility with hardcoded "mlib" paths in shared source code
- Consistent approach with source symlinks
Special Case - jlink Compatibility (1 example):
- example_resolved-modules uses JAR copying to mlib/ for simple names
- Necessary because jlink outputs actual JAR filenames in verbose mode
- Maintains golden master compatibility
Documentation Updates:
- Update READMEs for examples with special handling
- Document symlink approach and rationale
- Document JAR copying approach for jlink
- Clarify that symlinks are committed, not dynamically created
- Remove now-redundant comments about JAR locations
Minor Fixes:
- Standardize approach across all migrated examples
- Clean up obsolete comments in compile.sh and run.sh scripts
- Align .gitignore patterns with new structure
This completes the Maven Phase 2 migration, standardizing JAR creation
via Maven plugins while handling edge cases (dynamic loading, jlink)
with appropriate solutions (symlinks, JAR copying).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Introduced in the course of support-and-care/maven-support-and-care#137
Add two-part solution to handle mlib→target symlinks on Windows:
1. Enable symlink checkout in GitHub Actions
2. Recreate symlinks in compile.sh after target/ exists
The Problem:
On Windows, Git stores symlinks differently than Unix, and Java's
ModuleLayer API fails when loading modules through symlinks with:
java.nio.file.AccessDeniedException: .../m4/mlib
Root Cause:
- Git on Windows checks out symlinks before target directory exists
- Even with symlinks:true in actions/checkout@v4, Windows creates
symlinks that Java cannot traverse when target doesn't exist yet
- The target/ directory is only created during Maven compilation
The Solution (two parts):
Part 1 - GitHub Actions (.github/workflows/build.yml):
Add symlinks:true parameter to actions/checkout@v4 in both build-legacy
and build-m4 jobs to enable proper symlink checkout on Windows.
Part 2 - Compile Scripts (*/m4/compile.sh):
Recreate mlib→target symlinks after ensuring target/ exists:
mkdir -p target
if [ -L mlib ] && [ ! -e mlib ]; then
rm mlib # Remove broken symlink
fi
if [ ! -e mlib ]; then
ln -s target mlib # Create valid symlink
fi
This ensures:
- Unix systems use committed symlinks (work even if target missing)
- Windows gets valid symlinks recreated after target/ exists
- Both platforms can run Java code that uses ModuleLayer API
Affected files:
- .github/workflows/build.yml (checkout configuration)
- example_layer-hierarchy/m4/compile.sh
- example_layer-modules-grouped-in-hierarchy/m4/compile.sh
- example_layer-modules-module-resolution/m4/compile.sh
- example_patch/m4/compile.sh
All four examples use ModuleLayer API to dynamically load modules
from the mlib symlink at runtime.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Introduced in the course of support-and-care/maven-support-and-care#137
Move symlink validation/creation from compile.sh to run.sh to ensure it happens after Maven compilation completes. The Problem: Previously, compile.sh created the mlib→target symlink early, but then Maven's "mvn clean package" deleted target/, breaking the symlink on Windows. Even though we recreated it, Maven's clean goal invalidated it. The Solution: Move symlink creation to run.sh where it's actually needed: 1. compile.sh runs Maven compilation (which may delete/recreate target/) 2. run.sh validates and recreates mlib→target symlink if needed 3. Java code then uses the symlink to load modules via ModuleLayer API This ensures the symlink points to a fully populated target/ directory. Changes in all four examples: - compile.sh: Remove symlink creation, add note that run.sh handles it - run.sh: Add symlink validation/recreation before running Java code Affected examples: - example_layer-hierarchy/m4 - example_layer-modules-grouped-in-hierarchy/m4 - example_layer-modules-module-resolution/m4 - example_patch/m4 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> Introduced in the course of support-and-care/maven-support-and-care#137
Implement OS-conditional approach for mlib directory to avoid Windows
symlink issues with Java's ModuleLayer API.
The Problem:
On Windows, Java's ModuleLayer API fails when traversing symlinks with
AccessDeniedException. The root cause is Windows symlink semantics
differ from Unix, particularly when Java traverses symlinks.
The Solution:
Use OS-conditional logic in run.sh (detected via
${OS:-$(uname)} = "Windows_NT"):
Unix/macOS:
- Keep committed mlib→target symlink
- test -h mlib || ln -sfn target mlib (only create if missing)
- clean.sh preserves the symlink
Windows:
- Replace Git-checked-out symlink with directory
- test -d mlib || rm -f mlib (remove symlink if present)
- Copy JARs from target/ to mlib/
- clean.sh removes the directory
This approach:
- Preserves committed symlink on Unix (major development platform)
- Provides directory with copied JARs on Windows (CI platform)
- Minimal overhead (only copies on Windows)
- Same functionality on both platforms
Implementation:
1. Update run.sh: OS-conditional mlib creation
2. Update clean.sh: Only remove mlib on Windows
3. Update .gitignore: Add /mlib (ignored on Windows)
4. Update READMEs: Document OS-conditional approach using description lists
Affected examples (all use ModuleLayer API for dynamic module loading):
- example_layer-hierarchy/m4
- example_layer-modules-grouped-in-hierarchy/m4
- example_layer-modules-module-resolution/m4
- example_patch/m4
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Introduced in the course of support-and-care/maven-support-and-care#137
Add clickable code links to all 35 Maven 4 example implementations in the README.adoc table. Links point to the m4/ directory of each example. Changes: - README.adoc: Add 'code' links to all m4 migration status entries - README.adoc: Define :example-base: attribute (default for local viewing) - pom.xml: Add GitHub repository configuration properties - pom.xml: Configure example-base attribute for AsciiDoc processing - build.yml: Pass current branch name to Maven during doc generation The example-base attribute uses different values depending on context: - Local/GitHub viewing: 'jigsaw-examples' (relative paths) - CI/CD builds: Full GitHub URLs pointing to correct branch This ensures generated documentation always links to the correct source code on GitHub, whether built from main, feature branches, or PRs. Example link format: https://github.com/support-and-care/java9-jigsaw-examples/tree/<branch>/jigsaw-examples/example_xyz/m4/ 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> Introduced in the course of support-and-care/maven-support-and-care#137
Consolidate and enhance Netlify deployment workflow following the
pattern from maven-simple-reports project.
Changes:
- Add "Set Netlify alias" step to generate sanitized aliases
- PRs: pr-{number} (e.g., pr-4)
- Branches: sanitized branch name (e.g., feature-maven-4-migration)
- Consolidate two separate deployment steps into one
- Add "Display Netlify URL" step showing deployment info in summary
- Use commit message or PR title for deploy message
Benefits:
- Consistent, predictable aliases for all deployments
- Full Netlify URL prominently displayed in workflow summary
- Cleaner workflow with single deployment step
- Better traceability with descriptive deploy messages
Example summary output:
### 🚀 Netlify Deployment
✅ Deployed successfully!
🔗 URL: https://feature-maven-4-migration--java9-jigsaw-samples.netlify.app
📝 Alias: feature-maven-4-migration
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Introduced in the course of support-and-care/maven-support-and-care#137
and drop unknown checkout option (symlinks)
|
🚀 Deployed on https://pr-6--java9-jigsaw-samples.netlify.app |
Reorganize m4/src directory to follow proper Maven directory
structure with separate java/ and resources/ subdirectories for
each module. This change addresses Java compiler limitations with
symlinked source files.
Changes:
- Restructure m4/src with Maven-standard layout:
- src/{module}/main/java/ for Java source files
- src/{module}/main/resources/ for resource files
- Copy all source files (symlinks don't work with javac)
- Update pom.xml to read resources from new structure
- Add verify-sources.sh to ensure consistency with ../src
- Update verify.sh to call verify-sources.sh as Step 0
- Document structure and symlink limitation in README.adoc
Technical limitation: The Java compiler cannot resolve module
structure when source files are symlinked from outside the module
source path (--module-source-path). When javac encounters such
symlinks, it fails with "module not found on module source path"
errors. Therefore, m4/src/ contains full copies of all files from
../src/, reorganized into Maven's standard directory layout.
The verify-sources.sh script validates that all files remain
identical between ../src and m4/src despite different layouts,
running automatically as part of the verification workflow.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Introduced in the course of support-and-care/maven-support-and-care#137
f906b3e to
52b06ad
Compare
Compilation of Java Modules with Maven 4 / M4 Compiler Plugin follows convention-over-configuration approach by using src/<module>/<scope>/<language> directories by default. Introduced in the course of support-and-care/maven-support-and-care#137
Introduced in the course of support-and-care/maven-support-and-care#137
a28452a to
252f7d6
Compare
Maven 4.0.0-rc-5 includes the fix for the DefaultSourceRoot bug (apache/maven#10912, backported in #10917) that allows omitting <directory> elements from <source> declarations when using the default directory convention src/<module>/<scope>/<lang>. Changes: - Update CI workflow to use Maven 4.0.0-rc-5 - Add AsciiDoc include tags for Maven version (single source of truth) - Add [[recommended-maven4]] admonition in README.adoc - Add cross-reference to Maven 4 version recommendation 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> Introduced in the course of support-and-care/maven-support-and-care#137
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This PR completes Phase 2 of the Maven 4 migration, introducing Maven-based JAR packaging for all 35 migrated examples while maintaining backward compatibility with the existing shell script workflow.
Key Changes:
maven-jar-pluginMigration Details
Phase 2 Scope:
All 35 examples migrated to use Maven for JAR creation:
target/{module-name}.jarTechnical Approach:
javac→ Maven packagingmlib→target(Unix/macOS)compile.sh→run.shWindows Compatibility
Problem Solved:
Java's ModuleLayer API fails on Windows when traversing symlinks (AccessDeniedException).
Solution:
OS-conditional logic in
run.sh:mlib → targetsymlinkDocumentation & Infrastructure
Testing
Files Changed
200 files changed:
Major components:
pom.xmlfiles (JAR packaging configuration)compile.shscripts (Maven integration)run.shscripts (OS-conditional mlib handling)README.adocfiles (documentation).claude/transformations/maven-4-migration.md(transformation guide)Related Documentation
.claude/transformations/maven-4-migration.md🤖 Generated with Claude Code
Co-Authored-By: Claude noreply@anthropic.com
Introduced in the course of support-and-care/maven-support-and-care#137