JeKa: The Simplest Way to Publish on Maven Central
Jerome Angibaud

Jerome Angibaud @djeang

Joined:
Jan 19, 2023

JeKa: The Simplest Way to Publish on Maven Central

Publish Date: Dec 30 '24
-1 0

Update: This article now reference the new way for publishing, via Central Portal

JeKa is a modern Java build tool focused on simplicity.
This post demonstrates how to publish to Maven Central with minimal configuration.

Prerequisite: You need a Central Portal Accountto publish on Maven Central.

Configure and Run

With JeKa, you can fully configure the build by editing the jeka.properties file as follows:

jeka.version=0.11.37
jeka.java.version=17

jeka.classpath=dev.jeka:centralprotal-plugin

@project.moduleId=com.github.djeang:vincer-dom
@project.gitVersioning.enable=true

# Metadata required by Maven Central for publishing
@maven.pub.metadata.projectName=Vincer-Dom
@maven.pub.metadata.projectDescription=Modern Dom manipulation library for Java
@maven.pub.metadata.projectUrl=https://github.com/djeang/vincer-dom
@maven.pub.metadata.projectScmUrl=https://github.com/djeang/vincer-dom.git
@maven.pub.metadata.licenses=Apache License V2.0:https://www.apache.org/licenses/LICENSE-2.0.html
@maven.publication.metadata.developers=djeang:djeangdev@yahoo.fr
Enter fullscreen mode Exit fullscreen mode

Note that dependencies are listed in a dedicated dependencies.txt file to maintain clear separation of concerns.

[version]
org.junit:junit-bom:5.12.2@pom

[compile]

[test]
org.junit.platform:junit-platform-launcher
org.junit.jupiter:junit-jupiter
org.jdom:jdom2:2.0.6.1
Enter fullscreen mode Exit fullscreen mode

To publish to Maven Central, execute:

jeka project: pack centralportal: publish
Enter fullscreen mode Exit fullscreen mode

See a concrete example here.

GitHub action

The following Github Action workflow builds the project and publish to Maven Central:

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2
    - run: git fetch --prune --unshallow --tags
    - name: Build and publish
      env:
        JEKA_CENTRAL_PORTAL_USERNAME: ${{ secrets.CENTRAL_PORTAL_USERNAME }}
        JEKA_CENTRAL_PORTAL_PASSWORD: ${{ secrets.CENTRAL_PORTAL_PASSWORD }}
        JEKA_CENTRAL_PORTAL_SIGN_KEY: ${{ secrets.GPG_SECRET_KEY}}
        JEKA_CENTRAL_PORTAL_SIGN_KEY_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
      run: "./jeka build centralportal: publish"
Enter fullscreen mode Exit fullscreen mode

Thanks to its powerful wrapper, Jeka will install specified JDK and Jeka version by itself.

Explanations

Now that you know how to do it, let's explain how it works.

Jeka and Java Versioning

For better portability and reproducibility, we can declare both the Jeka and Java versions required for building. Both versions will be automatically downloaded if not already present on the host machine.

Specify Module ID and Versioning

The published moduleId is specified using the @project.moduleId property.

The version can be explicitly specified using the @project.version property. Note that properties can be set in the jeka.properties file or passed as a command-line argument: -D@project.version=1.0.1.

Instead, we choose to rely on Git to infer the version using: @project.gitVersioning.enable=true. If there is no tag on the current commit, the version will be set to [branch]-SNAPSHOT; otherwise, it will be the tag-name.

Provide secrets

To publish on Maven Central, we need to signs artefact files with the appropriate GPG key mentioned in Central Portal.

We also need to specify credentials at publication time.

For those, Jeka expects these values to be found in the followinng environment variables:

  • JEKA_CENTRAL_PORTAL_USERNAME: OSSRH account username
  • JEKA_CENTRAL_PORTAL_PASSWORD: OSSRH account password
  • JEKA_CENTRAL_PORTAL_SIGN_KEY: Armored GPG secret key as a string
  • JEKA_CENTRAL_PORTAL_SIGN_KEY_PASSPHRASE: The passphrase protecting the secret key

The content of JEKA_CENTRAL_PORTAL_SIGN_KEY can be obtained by executing: gpg --export-secret-key --armor MY-KEY.

Provide Publication Metadata

The mandatory metadata are set using @maven.pub.metadata.xxx properties.

Note that the @maven.pub.metadata.licenses property expects a format like: [license1 name]:[license1 url],[license2 name]:[license2 url],...

Automate Release Publication

By default, the published artefacts are automatically published to Maven Central. If you want to just validate your publication an publish to Maven Central manually (from Central Portal UI), you need to specify this configuration:

@centralportal.automatic=false
Enter fullscreen mode Exit fullscreen mode

Execute Build

To publish, simply execute: jeka project: pack centralportal: publish.

This will:

  • Create the JAR to publish (project: pack).
  • Create source and Javadoc JARs.
  • Generate the published POM file.
  • Compute all checksums.
  • Sign all published files.
  • Push everything to the Central Portal.

To see what will be published, execute: jeka maven: info.

Find more details here.

Comparison with Maven

The following is the Maven POM configuration equivalent for deploying a project to Maven Central:


<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <developers>
        <developer>
            <name>djeang</name>
            <email>djeangdev@yahoo.fr</email>
        </developer>
    </developers>

    <name>Vincer-DOM</name>
    <description>Modern Dom manipulation library for Java.</description>
    <url>https://github.com/djeang/vincer-dom</url>

    <groupId>com.github.djeang</groupId>
    <artifactId>vincer-dom</artifactId>
    <version>0.1.0-SNAPSHOT</version>

    <licenses>
        <license>
            <name>MIT License</name>
            <url>http://www.opensource.org/licenses/mit-license.php</url>
        </license>
    </licenses>

    <properties>
        <java.version>17</java.version>
        <maven-compiler-plugin.version>3.11.0</maven-compiler-plugin.version>
    </properties>

    <scm>
        <connection>scm:git:git://github.com/djeang/vincer-dom.git</connection>
        <developerConnection>scm:git:https://github.com/djeang/vincer-dom.git</developerConnection>
        <url>https://github.com/djeang/vincer-domr</url>
    </scm>

    <distributionManagement>
        <snapshotRepository>
            <id>ossrh</id>
            <url>https://s01.oss.sonatype.org/content/repositories/snapshots</url>
        </snapshotRepository>
        <repository>
            <id>ossrh</id>
            <url>https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/</url>
        </repository>
    </distributionManagement>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.junit</groupId>
                <artifactId>junit-bom</artifactId>
                <version>5.9.1</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
    <dependencies>
        <dependency>
            <version>org.junit.jupiter</version>
            <artifactId>junit-jupiter</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <version>org.junit.platform</version>
            <artifactId>junit-platform-launcher</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
             <version>org.jdom</version>
             <artifactId>jdom2</artifactId>
            <version>2.0.6.1</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <pluginManagement>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>${maven-compiler-plugin.version}</version>
                    <configuration>
                        <source>${java.version}</source>
                        <target>${java.version}</target>
                    </configuration>
                </plugin>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-source-plugin</artifactId>
                    <version>2.2.1</version>
                    <executions>
                        <execution>
                            <id>attach-sources</id>
                            <goals>
                                <goal>jar-no-fork</goal>
                            </goals>
                        </execution>
                    </executions>
                </plugin>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-javadoc-plugin</artifactId>
                    <version>2.9.1</version>
                    <executions>
                        <execution>
                            <id>attach-javadocs</id>
                            <goals>
                                <goal>jar</goal>
                            </goals>
                        </execution>
                    </executions>
                </plugin>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-gpg-plugin</artifactId>
                    <version>1.5</version>
                    <executions>
                        <execution>
                          <id>sign-artifacts</id>
                          <phase>verify</phase>
                          <goals>
                              <goal>sign</goal>
                          </goals>
                        </execution>
                    </executions>
                </plugin>
                <plugin>
                    <groupId>org.sonatype.central</groupId>
                    <artifactId>central-publishing-maven-plugin</artifactId>
                    <version>0.4.0</version>
                    <extensions>true</extensions>
                    <configuration>
                         <publishingServerId>central</publishingServerId>
                        <tokenAuth>true</tokenAuth>
                    </configuration>
                </plugin>
            </plugins>
        </pluginManagement>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
            </plugin>
            <plugin>
                <groupId>me.ccampo</groupId>
                <artifactId>git-version-maven-plugin</artifactId>
                <version>0.1.0</version> 
                <extensions>true</extensions>
                <configuration>
                    <strategy hint="git"/>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

Enter fullscreen mode Exit fullscreen mode

Conclusion

Jeka provides a simpler, yet powerful way to build Java software and publish artifacts to Maven Central or other repositories, with much less configuration and effort than traditional tools.

Visit the website, videos, and examples to get an idea of everything Jeka can do better.

Disclaimer: I am the author of Jeka.

Comments 0 total

    Add comment