Java Code Generator

The Java source code generator takes Pkl class definitions as an input, and generates corresponding Java classes with equally named properties.

The benefits of code generation are:

  • Configuration can be conveniently consumed as statically typed Java objects.

  • The entire configuration tree can be code-completed in Java IDEs.

  • Any drift between Java code and Pkl configuration structure is caught at compile time.

The generated classes are immutable and have component-wise implementations of equals(), hashCode(), and toString().

Installation

The code generator is offered as Gradle plugin, Java library, and CLI.

Gradle Plugin

See Installation in the Gradle plugin chapter.

Java Library

The pkl-codegen-java library is available from Maven Central. It requires Java 17 or higher.

Snapshots are published to repository https://s01.oss.sonatype.org/content/groups/public.

Gradle

To use the library in a Gradle project, declare the following dependency:

  • Kotlin

  • Groovy

build.gradle.kts
dependencies {
  implementation("org.pkl-lang:pkl-codegen-java:0.28.0-SNAPSHOT")
}

repositories {
  maven(url = "https://s01.oss.sonatype.org/content/groups/public")
}
build.gradle
dependencies {
  implementation "org.pkl-lang:pkl-codegen-java:0.28.0-SNAPSHOT"
}

repositories {
  maven { url "https://s01.oss.sonatype.org/content/groups/public" }
}

Maven

To use the library in a Maven project, declare the following dependency:

pom.xml
<project>
  <dependency>
    <groupId>org.pkl-lang</groupId>
    <artifactId>pkl-codegen-java</artifactId>
    <version>0.28.0-SNAPSHOT</version>
  </dependency>
  <repositories>
    <repository>
      <id>sonatype-s01</id>
      <name>Sonatype S01</name>
      <url>https://s01.oss.sonatype.org/content/groups/public</url>
    </repository>
  </repositories>
</project>

CLI

The CLI is bundled with the Java library. As we do not currently ship the CLI as a self-contained Jar, we recommend to provision it with a Maven compatible build tool as shown in Java Library.

Usage

The code generator is offered as Gradle plugin, Java library, and CLI.

Gradle Plugin

See Java Code Generation in the Gradle plugin chapter.

Java Library

The Java library offers two APIs: a high-level API that corresponds to the CLI, and a lower-level API that provides additional features and control. The entry points for these APIs are org.pkl.codegen.java.CliJavaCodeGenerator and org.pkl.codegen.java.JavaCodeGenerator, respectively. For more information, refer to the Javadoc documentation.

CLI

As explained in Installation, the CLI is bundled with the Java library. To run the CLI, execute the library Jar or its org.pkl.codegen.java.Main main class.

Synopsis: java -cp <classpath> -jar pkl-codegen-java.jar [<options>] <modules>

<modules>

The absolute or relative URIs of the modules to generate classes for. Relative URIs are resolved against the working directory.

Options

--generate-getters

Default: (flag not set)
Flag that indicates to generate private final fields and public getter methods instead of public final fields.

--generate-javadoc

Default: (flag not set)
Flag that indicates to preserve Pkl doc comments by generating corresponding Javadoc comments.

--params-annotation

Default: none if --generate-spring-boot is set, org.pkl.config.java.mapper.Named otherwise
Fully qualified name of the annotation type to use for annotating constructor parameters with their name.
The specified annotation type must have a value parameter of type String or the generated code may not compile. If set to none, constructor parameters are not annotated. Whether and how constructor parameters should be annotated depends on the library that instantiates the generated classes. For Spring Boot applications, and for users of pkl-config-java compiling the generated classes with -parameters, no annotation is required.

--non-null-annotation

Default: org.pkl.config.java.mapper.NonNull
Fully qualified name of the annotation type to use for annotating non-null types.
The specified annotation type must be annotated with @java.lang.annotation.Target(ElementType.TYPE_USE) or the generated code may not compile.

Common code generator options:

--indent

Default: " " (two spaces)
Example: "\t" (one tab)
The characters to use for indenting generated source code.

-o, --output-dir

Default: (not set)
Example: generated/
The directory where generated source code is placed. Relative paths are resolved against the working directory.

--generate-spring-boot

Default: (not set)
Flag that indicates to generate config classes for use with Spring Boot.

--implement-serializable

Default: (not set)
Flag that indicates to generate classes that implement java.io.Serializable.

--rename

Default: (none)
Example: foo.=com.example.foo.
Allows to change default class and package names (derived from Pkl module names) in the generated code.

When you need the generated class or package names to be different from the default names derived from the Pkl module names, you can define a rename mapping, where the key is the original Pkl module name prefix, and the value is its replacement. When you do, the generated code’s package declarations, class names, as well as file locations, will be modified according to this mapping.

The prefixes are replaced literally, which means that dots at the end are important. If you want to rename packages only, in most cases, you must ensure that you have an ending dot on both sides of a mapping (except for an empty mapping, if you use it), otherwise you may get unexpected results:

// Assuming the following arguments:
--rename com.foo.=x  // Dot on the left only
--rename org.bar=y.  // Dot on the right only
--rename net.baz=z   // No dots

// The following renames will be made:
"com.foo.bar" -> "xbar"       // Target prefix merged into the suffix
"org.bar.baz" -> "y..baz"     // Double dot, invalid name
"net.baz.qux" -> "z.qux"      // Looks okay, but...
"net.bazqux"  -> "zqux"       // ...may cut the name in the middle.

When computing the appropriate target name, the longest matching prefix is used:

// Assuming the following arguments:
--rename com.foo.Main=w.Main
--rename com.foo.=x.
--rename com.=y.
--rename =z.

// The following renames will be made:
com.foo.Main -> w.Main
com.foo.bar  -> x.bar
com.baz.qux  -> y.baz.qux
org.foo.bar  -> z.org.foo.bar

Repeat this option to define multiple mappings. Keys can be arbitrary strings, including an empty string. Values must be valid dot-separated fully qualified class name prefixes, possibly terminated by a dot.

Common CLI options:

--allowed-modules

Default: pkl:,file:,modulepath:,https:,repl:,package:,projectpackage:
Comma-separated list of URI patterns that determine which modules can be loaded and evaluated. Patterns are matched against the beginning of module URIs. (File paths have been converted to file: URLs at this stage.) At least one pattern needs to match for a module to be loadable.

--allowed-resources

Default: env:,prop:,package:,projectpackage:
Comma-separated list of URI patterns that determine which external resources can be read. Patterns are matched against the beginning of resource URIs. At least one pattern needs to match for a resource to be readable.

--color

Default: auto
When to format messages with ANSI color codes. Possible values:

  • "never": Never format

  • "auto": Format if stdin, stdout, or stderr are connected to a console.

  • "always": Always format

--cache-dir

Default: ~/.pkl/cache
Example: /path/to/module/cache/
The cache directory for storing packages.

--no-cache

Disable caching of packages.

-e, --env-var

Default: OS environment variables for the current process
Example: MY_VAR=myValue
Sets an environment variable that can be read by Pkl code with read("env:<envVarName>"). Repeat this option to set multiple environment variables.

-h, --help

Display help information.

--module-path

Default: (empty)
Example: dir1:zip1.zip:jar1.jar
Directories, ZIP archives, or JAR archives to search when resolving modulepath: URIs. Paths are separated by the platform-specific path separator (: on *nix, ; on Windows). Relative paths are resolved against the working directory.

-p, --property

Default: (none)
Example: myProp=myValue
Sets an external property that can be read by Pkl code with read("prop:<propertyName>"). Repeat this option to set multiple external properties.

--root-dir

Default: (none)
Example: /some/path
Root directory for file: modules and resources. If set, access to file-based modules and resources is restricted to those located under the specified root directory. Any symlinks are resolved before this check is performed.

--settings

Default: (none)
Example: mySettings.pkl
File path of the Pkl settings file to use. If not set, ~/.pkl/settings.pkl or defaults specified in the pkl.settings standard library module are used.

-t, --timeout

Default: (none)
Example: 30
Duration, in seconds, after which evaluation of a source module will be timed out. Note that a timeout is treated the same as a program error in that any subsequent source modules will not be evaluated.

-v, --version

Display version information.

-w, --working-dir

Base path that relative module paths passed as command-line arguments are resolved against. Defaults to the current working directory.

--ca-certificates

Default: (none)
Example: /some/path/certificates.pem
Path to a file containing CA certificates to be used for TLS connections.

Setting this option replaces the existing set of CA certificates bundled into the CLI. Certificates need to be X.509 certificates in PEM format.

For other methods of configuring certificates, see CA Certificates.

--http-proxy

Default: (none)
Example: http://proxy.example.com:1234
Configures HTTP connections to connect to the provided proxy address. The URI must have scheme http, and may not contain anything other than a host and port.

--http-no-proxy

Default: (none)
Example: example.com,169.254.0.0/16
Comma separated list of hosts to which all connections should bypass the proxy. Hosts can be specified by name, IP address, or IP range using CIDR notation.

Full Example

For a ready-to-go example with full source code, see codegen-java in the pkl/pkl-examples repository.