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.

Note: JPM is designed to be lightweight and fast, offering a modern alternative to traditional build tools like Maven and Gradle.
Features:
  • 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