Formats

A format is what lets a particular client talk to the repository: Maven and Gradle speak the Maven layout, a Jenesis build resolves module names through the module layout, docker speaks the OCI registry protocol, and curl can store plain files. Jenesis Repository ships four formats. Each is a discovered module on the server's module path, so a deployment speaks exactly the formats it carries, and every one of them stores its artifacts in the same content-addressed store.

Format Id Served at Clients
Maven layout maven /repository/maven/ Maven, Gradle, a Jenesis pom.xml build
Module layout jenesis /repository/module/ and /repository/artifact/ A Jenesis modular build, curl
OCI registry oci /v2/ docker, podman, any OCI client
Raw files raw /repository/raw/ curl, scripts, anything that can PUT

The Maven layout

/repository/maven/ is a drop-in Maven repository URL for publishing and resolving. A PUT stores the uploaded file content-addressed and links its path; a GET serves it back. Point a <distributionManagement> entry at the URL and mvn deploy publishes to it; a <repository> entry with the same URL resolves from it:

<distributionManagement>
  <repository>
    <id>jenesis</id>
    <url>http://localhost:8080/repository/maven/</url>
  </repository>
</distributionManagement>

The server stores what you upload and nothing more: it does not generate a POM for a jar, so publish the POM alongside the jar as a normal Maven deploy does. A published maven-metadata.xml is stored and served back verbatim. If you would rather have the server derive the version list from the artifacts it holds, opt in with jenreg.maven-metadata-compute=true: the document is then kept as a stored listing that every upload under the coordinate updates, and a read serves it as it is.

With an upstream configured (see Proxying), the same URL also serves everything from Maven Central, so one <mirror> entry covers your own artifacts and the public ones.

Every modular jar is a published module too

When a jar published to the Maven layout carries a module-info or an Automatic-Module-Name, the server reads the module name from the stored bytes and cross-publishes the jar into the module layout. A Jenesis build that declares requires <that module> then resolves it from the same server with no second upload. The bridge runs one way: a module published directly to the module layout stays there.

The module layout

The module layout resolves artifacts by Java module name, under the same URL shapes as the Jenesis Module Index:

GET /repository/module/<name>/<version>/<name>.jar     a specific version
GET /repository/module/<name>/<name>.jar               the latest version

A Jenesis build reaches it through jenesis.module.uri, exactly as it reaches the public index - so a private server and the public index are interchangeable from the build's point of view. A PUT under /repository/module/ or /repository/artifact/ stores a file at that path; most modules arrive through the Maven cross-publish above instead, which links the two /module/ shapes shown.

The OCI registry

The OCI format implements the Distribution API at /v2/, at the host root because the Docker protocol pins it there. docker push and docker pull talk to the server directly:

docker tag my-app repo.example.com/my-app:1.0
docker push repo.example.com/my-app:1.0
docker pull repo.example.com/my-app:1.0

It supports monolithic and chunked blob uploads, manifests addressed by tag or by digest (the media type is kept beside the manifest so a pull returns it verbatim), HEAD existence checks, tags/list, and _catalog. Both listings are stored documents a tag push keeps current, paged in memory for a client's n and last, so listing a registry of many images costs one read. An OCI blob is addressed by its sha256: digest, which is the very key the store uses, so image layers dedupe against everything else the repository holds. With an upstream registry configured, the same endpoint is a pull-through mirror (see Proxying).

Raw files

The raw format is a plain file store under /repository/raw/ for artifacts that belong to no ecosystem - installers, archives, datasets, signed binaries:

curl -T installer.msi http://localhost:8080/repository/raw/tools/installer-1.2.msi
curl    http://localhost:8080/repository/raw/tools/installer-1.2.msi -o installer.msi
curl    http://localhost:8080/repository/raw/tools/          # lists the directory
curl -X DELETE http://localhost:8080/repository/raw/tools/installer-1.2.msi

PUT stores a file content-addressed, GET serves it, GET on a trailing slash lists the directory, and DELETE removes the path. The bytes share the store with every other format, so a raw upload that matches a jar or an image layer costs no extra space.

Settings

Every format is on until you switch it off. jenreg.<id>=false (as an environment variable, JENREG_MAVEN=false, JENREG_JENESIS=false, JENREG_OCI=false, JENREG_RAW=false) keeps a format from activating, exactly as if its module were absent: its paths answer 404 and its importer is skipped.

Key Default Effect
jenreg.maven / jenreg.jenesis / jenreg.oci / jenreg.raw true Switch a format off with false.
jenreg.maven-metadata-compute false Derive maven-metadata.xml from stored versions instead of serving the uploaded file.
jenreg.proxy.<id> (unset) The upstream a format pulls through from; see Proxying.

A server with every format switched off is still a valid server - it answers 404 to every artifact request until a format is on to claim it.