Jeka - Reference Guide

Author : Jérôme Angibaud

Tool Part
Jeka Runtime
Jeka from Command line
Jeka Main Class
Parse the Command Line
Populate System Properties from Configuration Files and Command line
Compile Def Classes
Select CommandSet Class
Instantiate CommandSet Class
Invoke Methods Specified in Jeka Command Line arguments
Error Handling
Jeka from IDE
IDE Classpath Setting
Launch from IDE
Wrapper mode
Wrapper Mode in Multi-Project
Embedded Mode
Default Path Settings
Specify Jeka User Home
Specify the Local Repository Cache
See Effective Paths
CommandSet Parameters
Environment Variables
System Properties
Jeka Options
Inject Options
Retrieve Options as String Values
Retrieve Options in CommandSet Class Fields
Composite options
Document Options
Built-in Options
Binding Plugins
Modify JkCommandSet Instance
Configure Plugins in JkCommandSet Class
Document Plugins
Plugin version compatibility
Import External Runs
Declare Run Import
Option Propagation
Method propagation
Access Imported Runs Programmatically
Self Documentation
Classes from Jeka File API
Dependency Management
What is a dependency ?
What is a scope ?
What is a scoped dependency ?
Define a set of dependencies
HHierarchy of Dependency Types.
Dependencies on Module
Dependencies on local files
Dependencies on files produced by computation
Resolve Dependencies
Publish to a Maven repository
Publish to a Ivy repository
Java Project Building
Junit tests
Third Party Tool Integration


What is Jeka ?

Jeka is both a build library, and a thin automation tool.

The build library helps for dealing with file sets, compilation, dependency management, testing, publishing, launching external processes, crypto signatures... in a glance, all regular things you need to build/publish projects and especially Java projects. The library can be used in any Java program and does not have any dependency.

The tool aims at executing Java source code from the command line. Its design eases reuse of build elements (logic, settings, doc, ...) across projects.

Combined, it provides a full feature build tool with endless possibilities of extension.

Although library and tool are bundled in the same jar, the library does not depend on the tool at all.

What is this document for ?

This document stands for reference guide. It provides:

If you are looking for how exactly Jeka behaves, or you want to get a pretty exhaustive list of Jeka features, you are in the right place.

If you are looking for further details about API, please consult Javadoc or source code. Jeka source code has been written with intelligibility in mind in order to navigate easily from the user code to the Jeka engine room. For Java developers, reading source code and putting break points troubleshoots faster than documentation/support most of the time.

Jeka philosophy is to be transparent and easy to master. We hope that no user will ever feel the need to buy some trainings or books to master it.

Tool Part


The following concepts are used all over the tool section :

[PROJECT DIR] : Refers to the root folder of the project to build (or to run Jeka methods on). This is where you would put pom.xml or build.xml files.

[JEKA HOME] : Refers to the folder where Jeka is installed. You should find jeka.bat and jeka shell scripts at the root of this folder.

[JEKA USER HOME] : Refers to the folder where Jeka stores caches, binary repository and global user configuration. By default it is located at [USER DIR]/.jeka.

Def Classes : Java source files located under [PROJECT DIR]/jeka/def. They are compiled on the flight by Jeka when invoked from the command line.

Def Classpath : Classpath on which depends def classes to get compiled and Jeka classes to be executed. By default, it consists in Jeka core classes. it can be augmented with any third party lib or def Classpath coming from another project. Once def classes sources have been compiled, def Classpath is augmented with their .class counterpart.

Jeka Classes : Classes extending JkClass. Their commands can be invoked from the command line and their pubic fields set from the command line as well. Generally def classes contains one Jeka class though there can be many or none. CommandSet class can be a def class but can also be imported from a library or external project.

Jeka Methods : Java methods from Jeka classes which are invokable from Jeka command line. They must be instance method (not static), public, zero-args and returning void. Every method verifying these constraints is a command.

Options : This is a set of key-value used to inject parameters. Options can be mentioned as command line arguments, stored in specific files or hard coded in Jeka classes.

In a Glance

The Jeka tool consists in an engine able to run Java/Kotlin source code or compiled code from the command line.

Generally this code is intended to build Java projects but it can be used for any purpose.

In practice, your project has a structure respecting the following layout :

[Project Dir]
   + jeka
      + boot             <-------- Put extra jars here to augment def Classpath.
      + def
         +   <----- Class extending JkClass
         +    <---- Utility class consumed by MyCommands
         + OtherUtility.kt   <---- Kotlin code is also accepted
      + output              <---- Build artifacts are generated here
   + src
      + main
          + java
          + resources
   + ...

A command class may look like :

import dev.jeka.core.tool.JkClass;import dev.jeka.core.tool.JkDefClasspath;import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.GetMethod;
import dev.jeka.core.tool.JkDoc;

@JkDefClasspath("commons-httpclient:commons-httpclient:3.1")  // Imports 3rd party library to be used by def classes
public class MyCommands extends JkClass {    // The command class
    public String myParam1 = "myDefault";    // Overridable by injecting options in command line

    @JkDoc("Performs some tasks using http client")    // Only for self documentation purpose
    public void myMethod1() {                   // Run method (callable from command line)
        HttpClient client = new HttpClient();
        GetMethod getMethod = new GetMethod("http://my.url/" + myParam1);
    public void myMethod2() {   // An other run method 


From [Project Dir], you can invoke any command method defined on MyCommands class from the command line.

For example, executing jeka myMethod1 myMethod2 -myParam1=foo does the following :

  1. compile sources located in jeka/def directory,
  2. instantiate a MyCommands instance,
  3. inject "foo" in the myParam1 field,
  4. invoke myMethod1(),
  5. invoke myMethod2().

If no command class are present in def classes, Jeka picks JkClass. In despite this class does not provide any particular methods, you can still perform full Java builds by invoking built-in 'java' plugin. For such, execute jeka clean java#pack (See Plugins).

Executing jeka or jeka help on command line displays all run methods and options for the current command class.

The following chapters detail about how the mechanism works and what you can do with.

Jeka Runtime

This chapter describes how to use Jeka with command line and mostly what happens behind the cover when Jeka is run.

Jeka is a pure Java application requiring JDK version 8 or higher (tested until 12). JDK is required and JRE is not sufficient as Jeka uses the JDK tools to compile def classes.

Jeka classes can be launched both from command line and from your IDE as regular Java main method.

Jeka from Command line

To ease launching Java processes from command line, Jeka provides shell script jeka.bat and jeka. They are located at root of JEKA HOME which is supposed to be in your PATH environment variable.

This script does the following :

Jeka Main Class

Jeka entry point is dev.jeka.core.tool.Main#main method.

 1. Parse the command line.
 2. Populate system properties from configuration files and command line.
 3. Construct DEF CLASSPATH by parsing DEF CLASSES source code.
 5. Select the Jeka class to be run.
 6. Instantiate selected Jeka class, inject options and bind plugins on it.
 7. Invoke methods specified in command line arguments : methods are executed in the order they appear on the command line.

The following sub-sections detail about these steps.

Parse the Command Line

Jeka parses the command line and processes each arguments according the following pattern :

Populate System Properties from Configuration Files and Command line

Jeka loads system properties in order from :

The last loaded properties override the previous ones if there is some conflicts.

Jeka follows a similar process to load options. It loads in order :

The last loaded options override the previous ones if there is some conflicts.


In order to compile DEF CLASSES, Jeka has to compute DEF CLASSPATH first. With Jeka you can specify dependencies directly inside the source code using @JkDefClasspath or @JkDefImport annotations as shown below.

public class HttpClientTaskRun extends JkCommandSet {

    private OtherCommandSet otherCommandSet;  // CommandSet class from another project

To achieve this, Jeka parses source code of all classes under jeka/def and add the detected imports to the def Classpath. Note that classes having a name starting by a '_' are skipped.


When a dependency is expressed as a maven/ivy module, Jeka tries to resolve it against a binary repository.

Jeka defines this url by looking at following options, in order :

If a repository needs credentials, you need to supply it through Jeka options repo.[repo name].username and repo.[repo name].password.

Note that you can define several urls for a repo.[repo name].url by separating then with coma (as repo.def.url=http://my.repo1, http://my.repo2.snapshot).

As with other repo, if the download repository is an Ivy repo, you must prefix url with ivy: so for example you'll get repo.def.url=ivy:file://my.ivy/repo.

Compile Def Classes

Jeka compiles def class source files prior to execute it. Def class source files are expected to be in [PROJECT DIR]/jeka/def. Classes having a name starting by a '_' are skipped. If this directory does not exist or does not contains java sources, the compilation is skipped. Compilation occurs upon the following classpath :

It outputs class files in [PROJECT DIR]/jeka/.work/def-classes directory.

Jeka uses the compiler provided by the running JDK.

Select CommandSet Class

Once compiled, Jeka augments the def Classpath with classes compiled in previous step. Then it selects one Jeka class from def classpath and instantiate it.

The selection logic is :

Instantiate CommandSet Class

The Jeka class instantiation process is defined in ork.jeka.tool.JkCommandSet#of factory method. It consists in :

  1. Creating a new Jeka class instance (Invoking default constructor).
  2. Injecting defined options in public instance fields of the Jeka class and in the imported ones.
  3. Injecting fields options in the public instance fields of the bound plugins
  4. Initialising bound plugins (invoking JkPlugin#beforeSetup method)
  5. Invoking JkCommandSet#setup method on COMMAND CLASS. This method is supposed to be override to set specific settings.
  6. Invoking JkPlugin#afterSetup method on each bound plugins.
  7. Invoking JkCommandSet#postSetup on Jeka class. This method might be override.
  8. The Jeka class instance is ready.

Invoke Methods Specified in Jeka Command Line arguments

Once Jeka class instance is ready, Jeka invokes instance methods mentioned in command line as jeka myFistMethod mySecondMethod .... Jeka invokes methods, in same order they appear in command line regardless if method is defined on the Jeka class itself or in a plugin.

In order a method to be considered as a Jeka method (invokable from Jeka command line), it must :

If Jeka command line specifies no method, then Jeka invokes help.

Error Handling

If an exception is thrown during the execution, Jeka displays full stack trace on the console except if this is a JkException. In this case, Jeka displays only the message.

Jeka from IDE

IDE Classpath Setting

In order your IDE compiles and launches your def classes, you must ensure that project/module classpath contains :

Plugin methods eclipse#files and intellij#iml achieve this for you.

Launch from IDE

If launched from the IDE, def classes are already compiled and the classpath already set by the IDE. This leads in a simpler and faster process.

To launch Jeka from your IDE, you can go two ways :

One is to create a main method in one of your def classes as below and invoke it.

public static void main(String[] args) {
    JkInit.instanceOf(MyCommands.class, args).doSomething();

The JkInit#instanceOf method loads options from args and instantiates Jeka classes. Then user can configure it using hard coding prior launching any method programmatically.

The other way is to launch Main method from your IDE with same arguments as you would do with command line.

Wrapper mode

Jeka offers a wrapper mechanism similar to let execution independent of the Jeka version installed in host machine. This is the recommended way to use Jeka.

Wrapper consists in :

When executed in place of jeka, jekaw invoke the wrapper jar. This jar downloads the specified version of Jeka and pass the arguments to Jeka main class.

To start a project with a Jeka wrapper, just execute jeka scaffold#wrap at the root of the project. It will add the mentioned files above to your project. Then just invoke jekaw or ./jekaw in place of jeka.

Wrapper Mode in Multi-Project

If you are using multi-project structure, you don't have to scaffold wrapper on each. Just scaffold Jeka at a single place in your multi-project structure (for example in the root dir or in the 'master' project) and invoke it always from the sub project you want to build.

For example execute ../jekaw clean java#pack if the sub-project you want to build is located in a sub-directory of the root dir.

Embedded Mode

Embedded mode is the most aggressive strategy to not depend on the host machine. It consists in embedding Jeka tool itself within the project.

When launched from command line, [JEKA_HOME]/dev.jeka.jeka-core.jar comes after [WORKING_DIR]/jeka/boot/* in def classpath. This means that if a version of Jeka (dev.jeka.jeka-core.jar) is in this directory, the run will be processed with this instance of Jeka instead of the one located in in [JEKA HOME].

This is called the Embedded mode. The Jeka tool is embded within your project so the run does not depend of the presence and version of Jeka installed in the host machine.

__Enable embedded mode : __

To enable embedded mode :

  1. Copy [JEKA_HOME]/dev.jeka.jeka-core.jar into [PROJECT_DIR]/jeka/boot/* directory.
  2. Copy [JEKA_HOME]/jeka.bat and [JEKA_HOME]/jeka at the root of [PROJECT_DIR] (optional).

Jeka is provided with a scaffold plugin that do it for you : just execute jeka scaffold#run -scaffold#embed.

Run in embedded mode :

You can go two ways :

Default Path Settings

Specify Jeka User Home

Jeka uses user directory to store user-specific configuration and cache files, in this document we refer to this directory using [Jeka User Home]. By default this directory is located at [User Home]/.jeka ([User Home] being the path given by System.getProperty("user.home");. You can override this setting by defining the JEKA_USER_HOME environment variable.

Specify the Local Repository Cache

Jeka uses Apache Ivy under the hood to handle module dependencies. Ivy downloads and stores locally artifacts consumed by projects. By default the location is [JEKA USER HOME]/cache/repo but you can redefine it by defining the JEKA_REPO environment variable. You can get this location programmatically using JkLocator.getJekaRepositoryCache() method.

See Effective Paths

The Jeka displays the effective path at the very start of the process if launched with -LogHeaders=true option :

For example, jeka help -LogHeaders will output :

 _______     _
(_______)   | |
     _ _____| |  _ _____
 _  | | ___ | |_/ |____ |
| |_| | ____|  _ (/ ___ |
 \___/|_____)_| \_)_____|

                           The 100% Java build tool.

Working Directory : C:\Users\me\IdeaProjects\playground\jeka-sample
Java Home : C:\Program Files (x86)\Java\jdk1.8.0_121\jre
Java Version : 1.8.0_121, Oracle Corporation
Jeka Version : Xxxxx
Jeka Home : C:\Users\me\IdeaProjects\jeka\dev.jeka.core\jeka\output\distrib
Jeka User Home : C:\Users\me\.jeka
Jeka Repository Cache : C:\Users\me\.jeka\cache\repo


CommandSet Parameters

Jeka classes are parameterizable. One can retrieve values defined at runtime by reading :

Environment Variables

You can fetch environment variables using the standard System#getenv method or by annotating a public instance field with @JkEnv. JkOption mechanism takes precedence on environment variable injection.

System Properties

As for environment variables, one can read system properties using the standard System#getProperty method.

Jeka proposes 3 ways of injecting system properties. They are considered in following order :

In every case, defined system properties are injected after the creation of the java process (via System#setProperty method).

Jeka Options

Jeka options are similar to system properties as it stands for a set of key/value.

Options are globally available in all Jeka classes but can be retrieve in a static typed way (injected in Jeka class fields) or as set of key/string value.

Inject Options

Jeka proposes 3 ways to inject options. They are considered in following order :

Note for boolean options, when no value is specified, true will be used as default.

Retrieve Options as String Values

You can retrieve string values using the JkOptions API providing convenient static methods as JkOptions#get, JkOptions#getAll or JkOptions#getAllStartingWith(String prefix).

This way you only get the string literal value for the option and you have to parse it if the intended type was a boolean or a number.

Retrieve Options in CommandSet Class Fields

You can retrieve options just by declaring fields in Jeka classes. All public non-final instance fields of the invoked Jeka class, are likely to be injected as an option. Note that it can be private, but a public setter must be present.

For example, if you declare a field like :

class MyRun extends JkCommandSet {
   public int size = 10;

Then you can override the value by mentioning in command line jeka doSomething -size=5.

Note that the injected string value will be automatically converted to the target type.

Handled types are : String, all primitive types (and their wrappers), enum, File and composite object. If the value is not parsable to the target type, commands fails.

To get a precise idea on how types are converted see this code.

Composite options

Composite options are a way to structure your options. Say that you want to configure some server access with url, userName and passwsord. You can group all these information into a single object as :

public class Server {
    public String url;
    public String userName;
    public String password;
    // ...

Declare a new field of type Server in your Jeka class :

class MyRun extends JkCommandSet {
   public Server deployServer = new Server();

Then you can inject the server object using following options :


Document Options

If you want your option been displayed when invoking jeka help you need to annotate it with @JkDoc.

For example :

@JkDoc("Make the test run in a forked process")
public boolean forkTests = false;

Built-in Options

Jeka defines some built-in options that are used by the engine itself. Unlike regular options, they respect an UpperCamelCase naming convention :


Jeka provides a pluggable architecture. In Jeka, a plugin is a class extending JkPlugin and named as JkPlugin[PluginName]. The plugin name is inferred from Plugin class name.

Each plugin instantiated plugin is bound to a JkCommandSet object.

Plugins has 3 capabilities :

Jeka is bundled with a bunch of plugins (java, scaffold, eclipse, intellij, ...), but one can add extra plugins just by adding a jar or directory containing the plugin class to the def classpath.

To see all available plugins in the def classpath, just execute jeka help. See Command Line Parsing and Run Class Pre-processing to augment def classpath .

Binding Plugins

Plugins need not to be bound in Jeka class code in order to be bound to the JkCommandSet instance. Just the fact to mention a plugin in the command line loads it.

For example jeka scaffold#run java# will load 'java' and 'scaffold' plugins into a JkCommandSet instance. 'java' plugin instance will modify 'scaffold' plugin instance in such it produces a Jeka class declaring 'java' plugin when 'scaffold#run' is executed. It also creates Java project layout folders. See activate method in JkPluginJava Code to have a concrete view.

You can also force a plugin to be loaded in your Jeka class code as below. That way, you don't need to mention java# in command line.

public class MyBuild extends JkCommandSet {
    MyBuild() {
        getPlugin(JkPluginJava.class);  // Loads 'java' plugins in MyBuild instances, a second call on 'plugins().get(JkPluginJava.class)' would return the same JkPluginJava instance.
        getPlugin("intellij");   // You can also load plugins by mentioning their name but it's slower cause it involves classpath scanning

Modify JkCommandSet Instance

JkCommandSet instances are created using JkCommandSet#of factory method. This method invokes JkPlugin#beforeSetup and JkPlugin#afterSetup methods on all plugins loaded in the JkCommandSet instance. JkPlugin#afterSetup is supposed to be used to modify other plugins that might be bound to the owning Jeka class.

For example, Jacoco Plugin does not provide Jeka method but configures 'java' plugin in such unit tests are forked on a JVM with Jacoco agent on. It also provides a utility class JKocoJunitEnhancer that supplies lower level features to launch Jacoco programmatically.

Some other plugins does not modify their owning Jeka class instance. For instance, Scaffold Plugin just exposes methods to scaffold new Jeka projects.

Configure Plugins in JkCommandSet Class

There is three places where you can configure plugins :

Example of configuring a plugin in Jeka class.

    JkPluginSonar sonarPlugin = getPlugin(JkPluginSonar.class);  // Load sonar plugin 
    public MyBuild() {
		sonarPlugin.prop(JkSonar.BRANCH, "myBranch");  // define a default for sonar.branch property

Jeka own build class makes a good example.

Document Plugins

Plugin authors can embed self-documentation using @JkDoc annotation on classes, Jeka methods and option fields.

Writers can also mention that the plugin has dependencies on other plugins using @JkDocPluginDeps annotation. This annotation has only a documentation purpose and does not has impact on plugins loading mechanism.

A good example is Java Plugin

Plugin version compatibility

As Jeka API is likely to evolve (less and less), plugins author can mention the Jeka lower version on which the plugin is compatible with using JkPlugin#getLowestJekaCompatibleVersion method.

It is also possible to mention the highest version on Jeka, a plugin version is compatible with. As this information is unknown at the time of publishing the plugin, a mechanism based on a central registry keeps track this information.

It consists of publishing a specific format flat file on a url. The file contains the versions that start breaking compatibility. Project repository might host this registry.

A working example is available for spring-boot plugin. The breaking_versions.txt is accessible at declared in JkPluginSpringboot as :

protected String getBreakingVersionRegistryUrl() {
    return "";

Import External Runs

There is many way to perform multi-project build. One of is to import runs from external projects.


A Jeka class instance can import Jeka class instances from other projects.

The current def classpath is augmented with the def classpath of imported projects.

Imported runs are not aware they are imported. In fact any run can be imported. The relation is uni-directional.

Declare Run Import

To import a Jeka class from an external project, use the @JkDefImport annotation as shown below :

public class MyCommands extends JkCommandSet {
    private BarCommands importedCommands;  

    public void doSomesthing() {
       importedCommands.doBar();   // use the command class defined in ../otherProject

CommandSet classes are imported transitively, this means that, in above example, if BarCommands imports an other project, this last will be also imported.

Option Propagation

Options mentioned in command line are propagated to the imported Jekas.

So for example you execute jeka java#pack -java#tests.fork, test will be forked for the main run and all imported ones.

Method propagation

Methods mentioned in the command line are not automatically propagated to imported runs. Executing jeka clean will only clean the current run project.

To propagate method call to every imported Jeka classes, method name should be prefixed with a '*'. Executing jeka clean* will invoke 'clean' method on the current Jeka class along along all imported Jeka classes.

Access Imported Runs Programmatically

You can access to the list of imported Jeka classes within using JkCommandSet#getImportedCommandSets methods as show below :

public class MyRun extends JkCommandSet {


    public void doForAll() {
        this.getImportedCommandSets().getAllOf(JkJavaProjectBuild.class).forEach(build ->;

Self Documentation

CommandSet classes and plugins can provide self documentation.

When properly auto-documented, users can display documentation by executing jeka help.

The displayed documentation consist in :

If Jeka class or plugin declares a public instance field without @JkDoc annotation, then it will be displayed in help screen but mentioning that there is no description available.

If Jeka class or plugin declares a command without @JkDoc, it will be also displayed in help screen but mentioning that there is no description available.

This is the display screen for the Jeka project Jeka class :

Usage: jeka [methodA...] [pluginName#methodB...] [-optionName=value...] [-pluginName#optionName=value...] [-DsystemPropName=value...]
Execute the specified methods defined in Jeka class or plugins using the specified options and system properties.
When no method specified, 'doDefault' method is invoked.
Ex: jeka clean java#pack -java#pack.sources=true -LogVerbose -other=xxx -DmyProp=Xxxx

Built-in options (these options are not specific to a plugin or a build class) :
  -LogVerbose (shorthand -LV) : if true, logs will display 'trace' level logs.
  -LogHeaders (shorthand -LH) : if true, meta-information about the build creation itself and method execution will be logged.
  -LogMaxLength (shorthand -LML) : Console will do a carriage return automatically after N characters are outputted in a single line (ex : -LML=120).
  -CommandClass (shorthand -CC) : Force to use the specified class as the Jeka class to be invoked. It can be the short name of the class (without package prefix).

Available methods and options :

From class CoreBuild :
  Methods :
    doDefault : Conventional method standing for the default operations to perform.
  Options :
    -testSamples (boolean, default : false) : If true, executes black-box tests on sample projects prior ending the distrib.

From class JkCommandSet :
  Methods :
    clean : Cleans the output directory.
    help : Displays all available methods defined in this build.

Available plugins in classpath : eclipse, eclipsePath, intellij, jacoco, java, pgp, pom, repo, scaffold, sonar.

Type 'jeka [pluginName]#help' to get help on a perticular plugin (ex : 'jeka java#help').
Type 'jeka help -Plugins' to get help on all available plugins in the classpath.


Jeka contains a library for all regular things you need to build/publish projects and especially Java projects. It can be embedded in your own tool and used in a simple main method.

The Jeka-core jar embeds third party jars as Ivy or BouncyCastle. Those are not visible/accessible to client code due to a specific classloading mechanism, preventing version clashing with client dependencies.

API Style

Jeka tries to stick with a consistent API design style.

Class and Interface Naming Convention

All Jeka public classes/interfaces start with Jk. The reason is for easing distinction, in IDE, between classes supposed be used in production or test and the ones used for building. It also helps to explore Jeka API.

Mutable Vs Immutable

As a rule of thumb Jeka favors immutable objects for shallow structures and parent-chaining trees for deeper ones. Both provide a fluent interface when possible.


All objects are instantiated using static factory methods. Every factory method names start with of.

Read Accessors

All accessor method names (methods returning a result without requiring IO, only computation) starts with get.

Withers/Anders for Immutable Objects

To create a subtly different object from another immutable one, Jeka provides :

Setters/Adders for Mutable Objects

To modify a mutable object, Jeka provides :


To translate an object to another representation (for example a JkDependencySet to a list of JkScopedDependency) Jeka provides methods starting with to.

Domains Covered by the API

The previous example demonstrates how the Java/project API can be used to build and publish Java projects. This API relies on other lower level ones provided by Jeka. In a glance these are the domains covered by the Jeka APIs :


File manipulation is a central part for building software. Jeka embraces JDK7 java.nio.file API by adding some concepts around, to provide a powerful fluent style API performing recurrent tasks with minimal effort.

Classes from Jeka File API

The following classes lie in dev.jeka.core.api.file package:


// creates a file and writes the content of the specified url.

// copies all non java source files to another directory preserving structure
JkPathTree.of("src").andMatching(false, "**/*.java").copyTo("build/classes");

// One liner to zip an entire directory


The dev.jeka.core.api.system package provides system level functions :

Dependency Management


What is a dependency ?

For Jeka, a dependency is something that can be resolved to a set of files by a JkDependencyResolver. Generally a dependency is resolved to 1 file (or forlder) but it can be 0 or many.

A dependency is always an instance of JkDependency.

Jeka distinguishes 3 types of dependency :

For the last, Jeka is using Ivy 2.5.0 under the hood. This library is embedded inside the Jeka jar and is executed in a dedicated classloader. So all happens as if there where no dependency at all.

What is a scope ?

Projects may need dependencies to accomplish certain tasks and these dependencies may vary according the executed tasks. For example, to compile you may need guava library only but to test you'll need junit library too. To tag dependencies according their usage, Jeka uses the notion of scope (represented by JkScope class). This notion is similar to the Maven scope.

A scope can inherit from one or several scopes. This means that if a scope Foo inherits from scope Bar then a dependencies declared with scope Bar will be also considered as declared with scope Foo. For instance, in JkJavaBuild, scope TEST inherits from RUNTIME that inherits from COMPILE so every dependencies declared with scope COMPILE are considered to be declared with scope RUNTIME and TEST as well.

By default, scopes are transitive. This has only a meaning for module dependencies. If we have 3 modules having the following dependency scheme : A -> B -> C and the A-> B dependency is declared with a non transitive scope, then A won't depend from C.

JkJavaDepScope class pre-defines scopes used in Java projects.

Scope Mapping : Projects consuming artifacts coming from Ivy repository can also use JkScopeMapping which is more powerful. This notion maps strictly to the Ivy configuration concept.

What is a scoped dependency ?

A scoped dependency (represented by JkScopedDependency class) is simply a dependency associated with zero, one or many scopes.

Define a set of dependencies

To define a set of dependencies (typically the dependencies of the project to build), you basically define a set of scoped dependencies.

The set of scoped dependencies concept is represented by JkDependencySet class. This class provides a fluent API for easier instantiation.

import static dev.jeka.core.api.depmanagement.JkScopes.*;
JkDependencySet deps = JkDependencySet.of()
    .and("junit:junit:4.11", TEST)
    .and("org.mockito:mockito-all:1.9.5", TEST)

Note that :





HHierarchy of Dependency Types.

Dependencies on Module

This is for declaring a dependency on module hosted in Maven or Ivy repository. Basically you instantiate a JkModuleDepency from it's group, name and version.

        .and(JkPopularModule.GUAVA, "18.0")
        .and("com.orientechnologies:orientdb-client:[2.0.8, 2.1.0[")

There is many way to indicate a module dependency, see Javadoc for browsing possibilities.

Note that :

Dependencies on local files

You just have to mention the path of one or several files. If one of the files does not exist at resolution time (when the dependency is actually retrieved), build fails.

    JkDependencySet of()
        .andFile("libs/my.testingtool.jar", TEST);

Dependencies on files produced by computation

It is typically used for multi-modules or multi-techno projects.

The principle is that if the specified files are not found, then the computation is run in order to generate the missing files. If some files still missing after the computation has run, the build fails.

This mechanism is quite simple yet powerful as it addresses following use cases :

The generic way is to construct this kind of dependency using a java.lang.Runnable.

The following snippet constructs a set of dependencies on two external projects : one is built with Maven, the other with Jeka.

Path mavenProject = Paths.get("../a-maven-project");
JkProcess mavenBuild = JkProcess.of("mvn", "clean", "install").withWorkingDir(mavenProject);
Path mavenProjectJar = mavenProject.resolve("target/maven-project.jar");
JkJavaProject externalProject = JkJavaProject.ofSimple(Paths.get("../a-jeka-project")); 
JkDependencySet deps = JkDependencySet.of()
    .and(JkComputedDependency.of(mavenBuild, mavenProjectJar))

Resolve Dependencies

The JkDependencyResolver class is responsible JkDependencyResolver.of(JkRepo.ofMavenCentral());to resolve dependencies by returning JkResolveResult from a JkdependencySet.

JkDependencySet deps =  JkDependencySet

// Module dependencies are fetched from Maven central repo
JkDependencyResolver resolver = JkDependencyResolver.of(JkRepo.ofMavenCentral());  
JkResolveResult result = resolver().resolve(deps);

From the result you can :

JkDependencyNode slfjApiNodeDep = result.getDependencyTree().getFirst(JkModuleId.of("org.slf4j:slf4j-api"));
JkPathSequence sequence = result.getFiles();  
sequence.forEach(System.out::println); // print each files part of the dependency resolution

The following snippets captures the resolved dependency files for COMPILE scope. Junit is excluded from this result.

JkDependencySet deps = JkDependencySet.of()
    .and("org.slf4j:slf4j-simple", COMPILE_AND_RUNTIME)
    .and("junit:junit:4.11", TEST);
Iterable<Path> files = JkDependencyResolver.of(JkRepo.ofMavenCentral()).resolve(COMPILE).getFiles();


Jeka is able to publish on both Maven and Ivy repository. This includes repositories as Sonatype Nexus or Jfrog Artifactory.

Maven and Ivy have different publication model, so Jeka proposes specific APIs according you want to publish on a Maven or Ivy repository.

Publish to a Maven repository

Jeka proposes a complete API to pubish on Maven repository. POM files will be generated by Jeka according provided elements.

The following snippet demonstrate a pretty sophisticated publishing on Maven :

    JkVersionedModule versionedModule = JkVersionedModule.of("org.myorg:mylib:1.2.6");
    JkDependencySet deps = JkDependencySet.of()
            .and("org.slf4j:slf4j-simple", COMPILE_AND_RUNTIME)
            .and("junit:junit:4.11", TEST);
    JkMavenPublication mavenPublication = JkMavenPublication.of(Paths.get("org.myorg.mylib.jar"))

            // the following are optional but required to publish on public repositories.
            .and(Paths.get("org.myorg.mylib-sources.jar"), "sources")
            .and(Paths.get("org.myorg.mylib-javadoc.jar"), "javadoc")
            .withChecksums("sha-2", "md5")
            .withSigner(JkPgp.of(Paths.get("myPubring"), Paths.get("mySecretRing"), "mypassword"))
            .with(JkMavenPublicationInfo.of("My sample project",
                    "A project to demonstrate publishing on Jeka",
                    .andDeveloper("djeang", "", "", ""));

    // A complex case for repo (credential + signature + filtering) 
    JkRepo repo = JkRepo.of("http://myserver/myrepo")
            .withOptionalCredentials("myUserName", "myPassword")
                        .withFilter(mod -> // only accept SNAPSHOT and MILESTONE
                            mod.getVersion().isSnapshot() || mod.getVersion().getValue().endsWith("MILESTONE")
    // Actually publish the artifacts
    JkPublisher publisher = JkPublisher.of(repo);
    publisher.publishMaven(versionedModule, mavenPublication, deps);

Notice that Jeka allows to :

To sign with PGP, no need to have PGP installed on Jeka machine. Jeka uses Bouncy Castle internally to sign artifacts.

Publish to a Ivy repository

Publishing on Ivy repo is pretty similar than on Maven though there is specific options to Ivy.

    JkVersionedModule versionedModule = JkVersionedModule.of("org.myorg:mylib:1.2.6-SNAPSHOT");
    JkDependencySet deps = JkDependencySet.of()
            .and("org.slf4j:slf4j-simple", COMPILE_AND_RUNTIME)
            .and("junit:junit:4.11", TEST);

    JkIvyPublication publication = JkIvyPublication.of(Paths.get("org.myorg.mylib.jar"), "master")

    JkRepo repo = JkRepo.ofIvy(Paths.get("ivyrepo"));

    JkPublisher publisher = JkPublisher.of(repo);
    publisher.publishIvy(versionedModule, publication, deps, JkJavaDepScopes.DEFAULT_SCOPE_MAPPING,
  , JkVersionProvider.of());

Java Project Building package hosts classes to handle Java builds.

JkClassLoader and JkUrlClassloader Wrap a java.lang.ClassLoader adding convenient methods and classpath scanning capability.

JkClassPath A sequence of file to be used as a class path.

JkJarPacker A simple utility tyo create Jar or fat Jar file from compiled classes.

JkJavaCompiler Wraps either a Java Compiler tool, nor a javac process.

JkJavadocProcessor A Java source processor producing standard Javadoc

JkJavaProcess A utility to launch Java process (from class dirs or jars)

JkManifest Stands for the manifest file to include in jar files.

Junit tests package hosts three classes that let user launch test based on the Junit5 platform. This means that any test framework supported by Junit5 platform, is also supported by Jeka. Jeka also supports Junit4 out-of-the-box through the embedded vintage engine.

Jeka testing API mostly hides Junit Platform. For most of the cases, you won't need to code against Junit-Platform API to launch tests with Jeka. Nevertheless, Jeka allows users to code against Junit-Platform for fine-tuning.

JkTestProcessor This is the entry point to launch tests. Tests are executed using the current classloader classpath + extra class path mentioned in #launch method arguments.

JkTestResult The result of a test launch : count for found, failure, skip, success ...

JkTestSelection A mean to determine which test to launch. It can be set using file or tag filter. It is also possible to code against JUnit Platform


Projects are file structures for hosting Java projects meaning source code, test codes, dependencies, build instructions.

The principle is that each JkJavaProject holds everything needed to compile, test, pack and publish artifacts. The API embrace the parent-chaining pattern.

This is a pretty complete example taken from the Jeka build itself.

               .and("org.junit.jupiter:junit-jupiter-engine:5.1.0", TEST)
               .and("org.junit.vintage:junit-vintage-engine:jar:5.6.0", TEST)).__
                .addIncludePatternsIf(runIT, JkTestSelection.IT_INCLUDE_PATTERN).__.__
        .setRepos(JkRepoSet.ofOssrhSnapshotAndRelease(ossrhUser, ossrhPwd))
            .putArtifact(DISTRIB_FILE_ID, this::doDistrib)
            .putArtifact(WRAPPER_ARTIFACT_ID, this::doWrapper).__
                    .setDescription("Automate with plain Java code and nothing else.").__
                .addGithubDeveloper("djeang", "").__.__
            .append(() -> createGithubRelease());

You can define your onw specific artifact (distrib, binary specific,...). When defined, this artifact will be built and deployed along the other ones.

JkJavaProject instances are highly configurable. You can tune your project structure/build without limits.

Third Party Tool Integration

The dev.jeka.core.api.tooling package provides integration with tools developers generally deal with.


JkEclipseClasspathGenerator and JkEclipseProjectGenerator provides method to generate a proper .classpath and .project file respectively.

JkEclipseClasspathApplier reads information from a .classpath file.


JkIntellijImlGenerator generates proper .iml files.


JkGitWrapper wraps common Git commands in a lean API.


JkMvn wraps Maven command line in a lean API

JkPom reads POM/BOM to extract information like : declared dependencies, dependency management, repos, properties, version and artifactId.