Build a custom Meecrowave distribution in 1 line! The Microprofile example.
Apache Meecrowave has a Maven plugin to build a distribution zip from the current project. Basically it creates a zip with a bin/, conf/, lib/, logs/ folders. It fully matches Apache Tomcat layout and the meecrowave.sh script of the bin/ folder is exactly the catalina.sh of Tomcat. However the main difference is that lib/ classpath is deployed as an application instead of requiring the webapps/ folder.
Tip: you can still activate war deployments through the CLI if you want but it is not the default since it is less and less mainstream.
Now the question is how to provide a custom distribution where you just need to drop your jars in lib/ or specify the webapp to deploy through the CLI but not all libraries and services? To illustrate that we will take the Microprofile example.
Last version is the 1.4 or 2.0 (it leads to the same for Meecrowave), it is based on CDI+JAX-RS+JSON-P (+JSON-B for the v2) which is exactly Meecrowave and it adds Microprofile Config, Fault Tolerance, JWT-Auth, OpenTracing and Rest Client to complete the default set of specifications.
If you think in terms of Maven here is the dependencies pom:
<?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>
<groupId>org.microprofile</groupId>
<artifactId>microprofile-1.4</artifactId>
<version>1.4</version>
<name>Microprofile API + Implementations :: 1.4</name>
<packaging>pom</packaging>
<dependencies>
<!-- config -->
<dependency>
<groupId>org.eclipse.microprofile.config</groupId>
<artifactId>microprofile-config-api</artifactId>
<version>1.2.1</version>
<exclusions>
<exclusion>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.annotation.versioning</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.geronimo.config</groupId>
<artifactId>geronimo-config-impl</artifactId>
<version>1.2</version>
</dependency>
<!-- fault-tolerance -->
<dependency>
<groupId>org.eclipse.microprofile.fault-tolerance</groupId>
<artifactId>microprofile-fault-tolerance-api</artifactId>
<version>1.0</version>
<exclusions>
<exclusion>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.annotation.versioning</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.geronimo.safeguard</groupId>
<artifactId>safeguard-impl</artifactId>
<version>1.0</version>
</dependency>
<!-- jwt auth -->
<dependency>
<groupId>org.eclipse.microprofile.jwt</groupId>
<artifactId>microprofile-jwt-auth-api</artifactId>
<version>1.1</version>
<exclusions>
<exclusion>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.annotation.versioning</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.geronimo</groupId>
<artifactId>geronimo-jwt-auth</artifactId>
<version>1.0.0</version>
</dependency>
<!-- opentracing -->
<dependency>
<groupId>org.eclipse.microprofile.opentracing</groupId>
<artifactId>microprofile-opentracing-api</artifactId>
<version>1.1</version>
<exclusions>
<exclusion>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
</exclusion>
<exclusion>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.annotation.versioning</artifactId>
</exclusion>
<exclusion>
<groupId>javax.enterprise</groupId>
<artifactId>cdi-api</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-atinject_1.0_spec</artifactId>
</exclusion>
<exclusion>
<groupId>javax.ws.rs</groupId>
<artifactId>javax.ws.rs-api</artifactId>
</exclusion>
<exclusion>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>io.opentracing</groupId>
<artifactId>opentracing-api</artifactId>
<version>0.31.0</version>
</dependency>
<dependency>
<groupId>org.apache.geronimo</groupId>
<artifactId>geronimo-opentracing</artifactId>
<version>1.0.1-SNAPSHOT</version>
</dependency>
<!-- rest client -->
<dependency>
<groupId>org.eclipse.microprofile.rest.client</groupId>
<artifactId>microprofile-rest-client-api</artifactId>
<version>1.0.1</version>
<exclusions>
<exclusion>
<groupId>javax.enterprise</groupId>
<artifactId>cdi-api</artifactId>
</exclusion>
<exclusion>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
</exclusion>
<exclusion>
<groupId>javax.ws.rs</groupId>
<artifactId>javax.ws.rs-api</artifactId>
</exclusion>
<exclusion>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-rs-mp-client</artifactId>
<version>3.2.5</version>
</dependency>
</project>
Now the question is how to add it in lib/ and keeping the packaging simple? For that, Meecrowave bundle mojo (maven plugin) allows to specify a list of dependencies to add to its lib folder. By default it is not transitive so you would have to add all these dependencies one by one. This is very feasible in this case because, except geronimo-safeguard, they are all dependency free.
Here what it can look like:
<plugin>
<groupId>org.apache.meecrowave</groupId>
<artifactId>meecrowave-maven-plugin</artifactId>
<version>1.2.3</version>
<executions>
<execution>
<id>aggregator-bundle</id>
<phase>prepare-package</phase>
<goals>
<goal>bundle</goal>
</goals>
<configuration>
<attach>true</attach>
<classifier>microprofile-1.4</classifier>
<libs>
<lib>org.apache.geronimo:geronimo-config-impl:1.2</lib>
<lib>org.eclipse.microprofile.config:microprofile-config-api:1.2.1</lib>
<!-- etc -->
</libs>
</configuration>
</execution>
</executions>
</plugin>
This is great but it has one drawback: this will really build the right distribution but you can't use all the nice Meecrowave tooling for tests since you will miss it as dependencies and will need to add the dependencies - including implementations which is what we don't want - again in your application. To solve that we can create a pom like the previous one but it still relies on implementation.
The solution is to have a pom aggregating API and one aggregating implementations+API like the one at the beginning of this post. The API one is used as provided to develop and the last one is in scope test.
Now to create our common platform we can just reference the last pom in our plugin and request the transitive dependencies:
<plugin>
<groupId>org.apache.meecrowave</groupId>
<artifactId>meecrowave-maven-plugin</artifactId>
<version>1.2.3</version>
<executions>
<execution>
<id>aggregator-bundle</id>
<phase>prepare-package</phase>
<goals>
<goal>bundle</goal>
</goals>
<configuration>
<attach>true</attach>
<classifier>microprofile-1.4</classifier>
<libs>
<lib>org.microprofile:microprofile-1.4:1.0.0-SNAPSHOT:-:pom?transitive</lib>
</libs>
</configuration>
</execution>
</executions>
</plugin>
The "-" means there is no classifier in the library coordinates, the pom is the type of the artifact and ?transitive requests the plugin to import in lib/ all the dependency tree and not only this artifact.
At that moment of the post you probably think something like "it is cool, it makes the dev simpler but why would I do that myself"? And you are exactly right!
To solve that, Apache Geronimo created a microprofile repository which hosts all "inter-spec" informations. When writing these lines it hosts a Meecrowave flavor with all Geronimo Microprofile implementations (which is Microprofile 2.0 + health + openapi + metrics) called utilda (normally written as μ~ which just means "micro-wave" to show it is Microprofile on Meecrowave). This repository also hosts some pom aggregators (also usable as boms) with the dependency API and implementations. In short: it does all the work this post is about and just let you use it without effort :).
This project is quite recent and the user needs are still unclear so feel free to get in touch with Geronimo community through the mailing list to give your own feedback.
From the same author:
In the same category: