A command-line tool written in Rust to generate a Java project from a template (ZIP file or folder).
The binary reads a template (ZIP or folder), copies files to the destination directory while applying variable replacements in file paths and content. It also handles the transformation of the ${PACKAGE} variable into a Java folder hierarchy.
The main behavior is implemented in main via the Cli configuration structure and the extract_zip_with_replace, copy_dir_with_replace, and replace_package_in_path functions.
The following patterns are replaced in files and file names:
${PROJECT_NAME}${AUTHOR_NAME}${AUTHOR_EMAIL}${PROJECT_VERSION}${PACKAGE}(transformed into folder hierarchy, e.g.,com.example)${MAINCLASS}${PROJECT_YEAR}${JAVA}${VENDOR_NAME}
Depending on the --build option, the generator automatically adds:
- Maven (
pom.xml) if--build maven - Gradle (
build.gradle) if--build gradle
A .sdkmanrc file is always created with:
java=<java_flavor>(e.g.,25-zulu)maven=<version>if Maven build, orgradle=<version>if Gradle build
After project generation, the following files and directories are created:
.genrc- Configuration file in JSON format containing all generation parameters:- Project metadata (name, version, author, email)
- Build configuration (build tool, Java version, vendor name)
- Generation timestamp (
created_atin ISO 8601 format) - Generator metadata (
generated_with: command name and version) - Template source path
- Optional remote Git repository URL
Example .genrc content:
{
"project_name": "MyApp",
"author": "John Doe",
"email": "john@example.com",
"project_version": "1.0.0",
"package": "com.example.app",
"mainclass": "Application",
"java_version": "21",
"java_flavor": "21-zulu",
"build_tool": "maven",
"maven_version": "3.9.5",
"gradle_version": "8.5",
"vendor_name": "My Company",
"template": "templates/basic-java",
"remote_git_repository": null,
"created_at": "2025-11-26T14:30:45.123456+00:00",
"generated_with": {
"cmd": "genj",
"version": "1.3.1"
}
}.sdkmanrc- SDKMan environment configuration.vscode/- VSCode configuration directory withsettings.jsonandlaunch.json.git/- Git repository initialized with initial commitpom.xmlorbuild.gradle- Build configuration based on--buildoption
Requires Rust/Cargo. To compile:
cargo build --releaseAvailable shortcuts and options (see src/main.rs):
-t, --template <PATH>: Path to the template (ZIP or folder) [required]-d, --destination <DIR>: Destination directory [required]-n, --project_name <NAME>: Project name (default:Demo)-a, --author <NAME>: Author (default:Unknown Author)-e, --email <EMAIL>: Email (default:email@unknown.local)-v, --project_version <VER>: Project version (default:0.0.1)-j, --java_version <VER>: JDK version to target (e.g.,25) also used inpom.xml/build.gradle(default:25)-f, --java_flavor <LABEL>: JDK flavor for sdkman (e.g.,25-zulu) (default:25-zulu)-k, --package <PKG>: Java package (default:com.demo)-m, --mainclass <CLASS>: Main class (default:App)-b, --build <maven|gradle>: Build tool (default:maven)--maven_version <VER>: Maven version for.sdkmanrc(default:3.9.5)--gradle_version <VER>: Gradle version for.sdkmanrc(default:8.5)-l, --vendor_name <NAME>: Vendor name (usable in templates) (default:Vendor)--verbose: Enable verbose output for detailed debugging information
Examples:
- Generate from a template folder (Maven by default):
cargo run -- \
--template templates/basic-java \
--destination ./out \
--project_name Demo \
--author "Frédéric Delorme" \
--email fred@example.com \
--project_version 0.1.0 \
--package com.demo \
--mainclass App- Generate from a ZIP:
cargo run -- --template /path/to/template.zip --destination ./out --project_name Demo- Force Gradle and specify versions in
.sdkmanrc:
cargo run -- \
--template templates/basic-java \
--destination ./out \
--project_name Demo \
--build gradle \
--gradle_version 8.5 \
--java_flavor 25-zulu- Target a specific JDK version for compilation (used in
pom.xmlandbuild.gradle):
cargo run -- --template templates/basic-java --destination ./out --project_name Demo -j 25Enable verbose output to see detailed information about each step of the generation process:
cargo run -- \
--template templates/basic-java \
--destination ./out \
--project_name Demo \
--verboseOutput with --verbose:
=== genj - Java Project Generator ===
Version: 1.3.1
Verbose mode enabled
[VERBOSE] Destination path will be: ./out/Demo
[VERBOSE] Generation timestamp: 2025-11-26T14:30:45.123456+00:00
[VERBOSE] Replacement variables:
${PROJECT_NAME} = Demo
${AUTHOR_NAME} = Unknown Author
...
[INFO] Reading template from: templates/basic-java
[VERBOSE] Template detected as directory
[VERBOSE] Scanning source directory: templates/basic-java
[VERBOSE] Created directory: ./out/Demo/src/main/java/com/demo
[VERBOSE] Copied and replaced: ./out/Demo/src/main/java/com/demo/App.java
[✓] Template directory copied
[INFO] Using build tool: maven
[VERBOSE] Generating pom.xml
[✓] pom.xml generated
[✓] .sdkmanrc generated
[✓] .genrc configuration file generated
[INFO] Configuring VSCode and Git repository...
[VERBOSE] Initializing Git repository
...
[✓] Java project 'Demo' generated successfully in ./out/Demo
=== Generation Summary ===
Project Name: Demo
Package: com.demo
Build Tool: maven
Java Version: 25
Location: ./out/Demo
Verbose mode is useful for:
- Debugging template processing issues
- Verifying variable replacements
- Checking file and directory operations
- Understanding the generation workflow
- Troubleshooting file copy failures
Example templates can be found in templates/ (e.g., templates/basic-java). You can use them as is or create your own template (folder or ZIP). The structure can contain ${PACKAGE} in paths so that the generator creates the corresponding subfolders.
- Cargo configuration:
Cargo.toml - Program entry point and logic:
src/main.rs
- The program creates the destination directory
<destination>/<project_name>. - If the template is a ZIP, the script attempts to remove a common root prefix present in the archive.
- Binary files detected (non-text) are copied as is; only text files undergo replacements.
- The
.genrcfile stores the exact parameters used for generation and can be used to regenerate similar projects.
Two helper scripts are provided to produce release artifacts and Debian packages:
-
build-release-full.sh
- Purpose: compile a release build and collect artifacts (release binary, man pages, docs, LICENSE, README, etc.) into a release directory and an archive (tar.gz).
- Usage:
chmod +x build-release-full.sh ./build-release-full.sh
- Result: a release archive (and/or release directory) is produced in the repository (see script output for exact path). Use this to distribute prebuilt binaries.
-
build_deb.sh
- Purpose: build a Debian package (.deb) that installs the
genjbinary and man pages (section 1 and section 5), plus documentation. - Usage:
chmod +x build_deb.sh ./build_deb.sh
- Result: a Debian package
genj_<version>_<arch>.debis created in the project root. Install with:sudo dpkg -i genj_<version>_<arch>.deb
- Purpose: build a Debian package (.deb) that installs the
Make both scripts executable before running:
chmod +x build-release-full.sh build_deb.shThe project includes build_deb.sh which automates packaging into a .deb. The script:
- Compiles the project in release mode
- Creates the Debian package layout (including
/usr/binand/usr/share/man) - Copies and compresses man pages (genj.1 and genj-template.5) into appropriate sections
- Creates maintainer scripts (postinst, prerm, postrm) and documentation under
/usr/share/doc/genj - Builds the .deb
Installing the generated package:
sudo dpkg -i genj_1.2.2_amd64.debVerification:
which genj
man genj
man genj-template
genj --help