JPM - JVM Package Manager
A simple and efficient build tool and package manager for Java and Kotlin projects. JPM provides a better approach to managing dependencies, building, running, and testing Java/Kotlin applications, inspired by npm.
- Simple Configuration: YAML-based project configuration
- Multiple Dependency Sources: Maven, JPM, raw files, custom repositories
- Hot Reloading: Development with automatic reloading
- Cross-Platform: Works on Windows, macOS, and Linux
- Testing Support: Integrated JUnit testing
- Custom Scripts: Define and run custom commands
- Bundle Creation: Create JAR files with dependencies
Setup JPM Environment
After adding jpm to your PATH, set up the JPM environment with required tools:
# look for problems with jpm
jpm doctor
# fix the problems
jpm doctor -fix
Quick Start
1. Initialize a new project
# this will create app/App.java
jpm init
# or , this will create a src/main/java/com/example/App.java and initialize a git repo
jpm init src/main/java/com.example.App -git
2. Compile and run
jpm start
Project Structure
A typical JPM project structure:
my-project/
├── package.yml # Project configuration
├── app/ # Source code
│ └── App.java
├── tests/ # Test files
│ └── TestApp.java
├── jpm_dependencies/ # Dependencies
│ └── tests/ # Test dependencies
│ └── execs/ # Exec dependencies
├── out/ # Compiled classes
└── .gitignore # Git ignore file
Configuration
package.yml
The main configuration file is an example of a package.yml that defines your project:
main: com.example.MyApp
package: example
version: 1.0.0
language: java
src: .
description: an example project
env: .env
scripts:
start: jpm compile && jpm run
dev: jpm watch "(src/**)" "jpm start"
clean: rm -rf out/*
dependencies:
- org.apache.commons commons-lang3:latest
- org.openjfx javafx-control
repos:
- deafult: https://repo1.maven.org/maven2/
excludes:
- commons-lang3
classifiers:
javafx-control: linux
args:
java: -Xmx512m
javac: -source 17 -target 17
kotlinc: -no-stdlib
junit: --reports-dir=../reports
hotswap: autoHotswap=false
Configuration Fields
| Field | Description |
|---|---|
package |
Project package name (required) |
description |
Project description |
main |
The main class to run (e.g., com.example.MyApp) |
version |
Project version |
env |
.env file location (you can get the values of keys with System.getenv("KEY")) |
src |
Project source dir (usually just . or src/main/java) |
language |
Programming language (java or kotlin or java,kotlin) |
scripts |
Custom commands (see Scripts section) |
dependencies |
Project dependencies (see Dependencies section) |
excludes |
list of excludes package names or artifactIDs |
classifiers |
map of classifiers keys can be package name, artifactIDs, groupIDs or "*" - org.openjfx: win -> example of classified groupID |
repos |
Repository configurations - mvn: https://repo1.maven.org/maven2/ -> example of repository, preppend all dependencies with mvn to install from that specific repository, default means no need to preppend anything. |
args |
Command-line arguments for different operations - java -> executes on the java command- javac -> executes on the javac command- kotlinc -> executes on the kotlinc command- junit -> args are added to junit5 jar- hotswap -> args added to hotswap-agent |
Commands
Project Management
jpm init [project_name] [options]
Initialize a new Java project.
# Basic initialization
jpm init
# Basic initialization of a kotlin app
jpm init new-app.App -kt
# With Git repository
jpm init new-app -git
# With Dockerfile
jpm init src/main/kotlin/com.example.myapp.MyApp -kt -docker
jpm create <template>
Create a project from a template.
# looks up jpm's repository for simple-spring-app template
jpm create simple-spring-app
# looks up the working dir for simple-spring-app.yml template
jpm create -yml simple-spring-app.yml
Development
jpm compile
Compile the source code under the package source dir and package dir.
jpm compile
jpm run [options] [...appArgs]
Run the compiled application.
# Basic run
jpm run
# Basic run with args
jpm run appArg1 appArg2
# With watch mode (hot reloading)
jpm run -hot
# Omitting the watch args and applying your application args
jpm run -hot _ _ appArg1 appArg2
# With custom arguments on each file .java or .html change
jpm run -hot "(src/**.java|src/**.html)" "echo reloading" appArg1
jpm watch [pattern] [command]
Watch for file changes and execute commands.
# Watch all files under src and compile
jpm watch
# Watch all Java files and run tests
jpm watch "(src/**.java)" "jpm test"
# Watch specific pattern and start
jpm watch "(src/com/example/**.java)" "jpm start"
Testing
jpm test
Run tests using JUnit.
jpm test
Dependency Management
jpm install
Install all dependencies from package.yml.
jpm install
# force a re-resolving of all dependencies (delete jpm_dependencies to re-install)
jpm install -f
jpm install <dependency> [scope]
Install a specific dependency.
# Install from JPM repository
jpm install my-library
# Install from Maven repository if maven is set as default repository
jpm install org.apache.derby derby:10.17.1.0
# Install from custom repository if alias was set in package.yml
jpm install my-repo org.example library:1.0.0
# Install raw JAR file
jpm install raw https://example.com/library.jar
# Install with extraction
jpm install raw -x https://example.com/library.zip
# Install with scope
jpm install my-library:1.0.0 test
jpm install concurrently:1.0.0 exec
jpm install -repo <alias>:<url>
Add a new repository.
jpm install -repo mvn:https://repo1.maven.org/maven2/
Building
jpm bundle [options]
Create a JAR bundle.
# Create basic JAR
jpm bundle
# Create fat JAR (all dependencies included, not yet surported)
jpm bundle -fat
# Create a executable JAR with scripts
jpm bundle -exec
# Create a executable JAR with scripts, creates dependencies.json and a MD file.
jpm bundle -publish
# Create a executable JAR with scripts, creates dependencies.json and a MD file.
# keeps the classifiers you've set in you project in dependencies.json
jpm bundle -publish --keep-classifiers
System
jpm doctor
Check JPM installation and dependencies.
jpm doctor
jpm setup <component>
Setup JPM components.
# Setup Java for HotSwap Agent
jpm setup -java
# Setup Kotlin
jpm setup -kotlin
# Setup JUnit
jpm setup -junit
# Setup HotSwap Agent
jpm setup -hotswap
# toggle verbosity
jpm setup -v
# install git (especially for windows)
jpm setup -git
# installs openjdk
jpm setup -jar
# setup jpx to execute you exec dependencies on the cli
jpm setup -jar
Custom Scripts
You can run custom scripts defined in package.yml:
jpm <script-name>
if you have a script called run@ in your package.yml, it overrides the default jpm run to your custom command.
example for jpm init
$ jpm init
Overriding: 'jpm init' for 'jpm init@'
You can append the rest of the command provided to jpm by adding ...args@ to the script
this way you can still use jpm install with args, but it'll also download image.png
scripts:
install@: |
wget -O resources/image.png https://openimage.com/images/image.png
jpm install ...args@
Dependencies
JPM supports multiple types of dependencies:
Maven Dependencies
dependencies:
# installs derby for the project
- org.apache.derby derby:latest
# installs springboot's test libraries in a test scope
- org.springframework.boot spring-boot-starter-test test
JPM Dependencies
dependencies:
# installs my-devDependecny in the exec scope, it makes it executable in scripts
- my-devDependency:1.0.0 exec
# installs neutron from jpm's repository
- neutron
Raw Dependencies
dependencies:
- raw https://example.com/library.jar exec # custom jar now available for execution
- raw -x https://example.com/library.tar.gz # tar.gz extraction support
- raw -x https://example.com/library.zip # zip extraction support
Repository Dependencies
dependencies:
# custom POM repository using the alias "my-repo", you have to preppend this alias to use the repository
- my-repo org.example library:1.0.0
repos:
- my-repo: https://my-custom-repo.com/repository/
Dependency Scopes
- test: Available only for testing
- exec: Executable dependencies to run with
jpx
Scripts
Define custom scripts in your package.yml:
port: "8090"
scripts:
dev: jpm run -hot {{ port }}
start: jpm compile && jpm run {{ port }}
clean:deep: |
echo cleaning
rm -rf out
rm -rf dist
rm -rf jpm_dependencies
build: jpm compile && cp ressourses/* out/
String Substitution
1. You can substitute an arbitrary string in the package.yml
springVerison: 3.5.5
dependencies:
- org.springframework.boot spring-boot-starter-web:{{ springVerison }}
2. You can substitute an arbitrary key=value in the .env file
env: .env
scripts:
start: jpm compile && jpm run --server.port={{ env.PORT }}
3. You can substitute an arbitrary environment variable with ENV.
shell:
$ JFX=mac jpm install
package.yml:
classifiers:
org.openjfx: "{{ ENV.JFX }}"
4. You can substitute platform information with jpm.
package.yml:
scripts:
print-info: echo {{ jpm.OS }} {{ jpm.ARCH }} {{ jpm.OS-ARCH }}
shell:
$ jpm print-info
linux amd64 linux-amd64