How to publish a Micronaut project using Gradle
Tags: micronaut, gradle, devops, maven
Published: 2021-04-17 03:22:30

I have really enjoyed working with Micronaut.  It's a wonderfully fast framework that makes life easier.  This new framework is really easy to get up and running.  Publishing on the other hand isn't well documented, so I wanted to share some tips on how I was able to get this done.

## Overview
We will specifically be publishing a Micronaut app using Gradle.  You will need to install the Micronaut CLI.  You can grab it here: https://guides.micronaut.io/micronaut-cli/guide/index.html

## Create a Micronaut App
Now that you've grabbed the CLI, create a new project.  The Launcher button on the Micronaut site will help you with the CLI commands if you want specific packages.  But for the sake of simplicity, we won't be installing anything special.  Run the following command to build a demo app:

```
$ mn create-app --build=gradle --jdk=11 --lang=java --test=junit to.dev.publishing
```

## Gradle Steps
If you're like me, you might have IntelliJ with the Gradle plugin installed.  If so, this next part is a no brainer.  By simply opening the project it will run Gradle in the background and generate your project.  You should have a `build.gradle` file in the root of your project that looks something like this:

```groovy
plugins {
    id("com.github.johnrengelman.shadow") version "6.1.0"
    id("io.micronaut.application") version "1.4.2"
}

version = "0.1"
group = "to.dev"

repositories {
    mavenCentral()
}

micronaut {
    runtime("netty")
    testRuntime("junit5")
    processing {
        incremental(true)
        annotations("to.dev.*")
    }
}

dependencies {
    implementation("io.micronaut:micronaut-http-client")
    implementation("io.micronaut:micronaut-runtime")
    implementation("javax.annotation:javax.annotation-api")
    implementation("io.micronaut:micronaut-validation")
    runtimeOnly("ch.qos.logback:logback-classic")
}


application {
    mainClass.set("to.dev.Application")
}
java {
    sourceCompatibility = JavaVersion.toVersion("11")
    targetCompatibility = JavaVersion.toVersion("11")
}
```
## Running Gradle Build
Run the following command to build your artifacts:
```
$ ./gradlew build

> Task :compileTestJava
Note: Creating bean classes for 1 type elements

BUILD SUCCESSFUL in 11s
15 actionable tasks: 3 executed, 12 up-to-date
```
Your output may be slightly different depending on your dependencies and workstation.

## Artifacts
To see the produced artifacts you can run:
```
$ ls ./build/libs/
publishing-0.1-all.jar
publishing-0.1-runner.jar
publishing-0.1.jar

```
Hmm... Interesting right?  We have 3, so which one is should we ship to production?  The short answer, is `publishing-0.1-all.jar`.  But how do we publish it?  And what are the other two JARs for? (we'll discuss this on another post)

## Publishing
It took some time to understand the best publishing strategy for my current use-case.  What I wanted were the following 3 things:

- The primary JAR
- A Zip archive of the distribution
- A Tar archive of the distribution

Ok.  Great... So how do we do that?  Add the following lines to your `build.gradle` file:

```
publishing {
    publications {
        myDist(MavenPublication) {
            artifact shadowJar
            artifact distZip
            artifact distTar
        }
    }
}
```

And that's it!  `shadowJar` produces our large `publishing-0.1-all.jar`.  The zip/tar produce the full distribution which includes all the required JAR files for your project.

## Publishing to Maven Locally "Trick"
So you're not quite ready to publish to Maven Central, Nexus3 or Artifactory.  No biggie.  You can use the following "trick" to publish to your local machine.  This is useful if you want to inspect distribution you can delete your local `~/.m2` directory:

```
$ rm -rf ~/.m2
```
Afterwards, from your project repo run the following Gradle command:
```
$ ./gradlew publishMyDistPublicationToMavenLocal
```
Now you can inspect your "published" artifacts:
```
$ find ~/.m2
/Users/johnny/.m2
/Users/johnny/.m2/repository
/Users/johnny/.m2/repository/to
/Users/johnny/.m2/repository/to/dev
/Users/johnny/.m2/repository/to/dev/publishing
/Users/johnny/.m2/repository/to/dev/publishing/maven-metadata-local.xml
/Users/johnny/.m2/repository/to/dev/publishing/0.1
/Users/johnny/.m2/repository/to/dev/publishing/0.1/publishing-0.1-all.jar
/Users/johnny/.m2/repository/to/dev/publishing/0.1/publishing-0.1.pom
/Users/johnny/.m2/repository/to/dev/publishing/0.1/publishing-0.1.tar
/Users/johnny/.m2/repository/to/dev/publishing/0.1/publishing-0.1.zip

```

## Takeaways
- Micronaut is amazing and I love it.  It's still quite new and documentation is hard.  Getting up and running is fast, but publishing isn't super obvious at first glance.

- Even without selecting it, our CLI command includes the Netty webserver.  I think its pretty slick coming from a WAR/Tomcat background!  Netty completely sidesteps the Servlet.

- Gradle is awesome.  As a UNIX expert my heart will always go out to to Make, but come on people its 2021!

I hope this helps save you some time.  It took me a little bit to figure this one out.