adam bien's blog

Simplest Possible Quarkus Extension 📎

A quarkus extension comprises two maven modules (runtime and deployment):

<modelVersion>4.0.0</modelVersion>
<groupId>com.airhacks</groupId>
<version>0.0.5</version>
<artifactId>quarkus-airhacks-extension-parent</artifactId>
<packaging>pom</packaging>
<modules>
    <module>runtime</module>
    <module>deployment</module>
</modules>    

The runtime module contains the implementation of the functionality. In our sample it is a simplistic Servlet:


import java.io.IOException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


@WebServlet
public class AirhacksServlet extends HttpServlet {

    public AirhacksServlet() {
        System.out.println("AirhacksServlet()");
    }

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
        response.getWriter().print("hello from airhacks extension");
    }
}
    
The responsibility of the deployment module is the exposure of metadata and configuration as early in the build cycle, as possible:

package com.airhacks;

import io.quarkus.deployment.annotations.BuildStep;
import io.quarkus.deployment.builditem.FeatureBuildItem;
import io.quarkus.undertow.deployment.ServletBuildItem;

class AirhacksProcessor {

    static final String FEATURE_NAME = "airhacks-extension";

    @BuildStep
    ServletBuildItem createAirhacksServlet() {
        System.out.println("AirhacksProcessor.createAirhacksServlet");
        ServletBuildItem servletBuildItem = ServletBuildItem.builder(FEATURE_NAME, AirhacksServlet.class.getName())
                .addMapping(FEATURE_NAME)
                .build();
        return servletBuildItem;
    }

    @BuildStep
    FeatureBuildItem createFeatureItem() {
        System.out.println("AirhacksProcessor.createFeatureItem");
        return new FeatureBuildItem(FEATURE_NAME);
    }

}    

A quarkus project (create with: mvn io.quarkus:quarkus-maven-plugin:[CURRENT_VERSION]:create) needs to declare the dependency to the runtime module:


<dependency>
    <groupId>com.airhacks</groupId>
    <artifactId>quarkus-airhacks-extension</artifactId>
    <version>0.0.5</version>
</dependency>    

mvn install produces the following output:


[io.quarkus.deployment.QuarkusAugmentor] Beginning quarkus augmentation
[org.jboss.threads] JBoss Threads version 3.0.0.Beta4
AirhacksProcessor.createFeatureItem
AirhacksProcessor.createAirhacksServlet
...indicating both BuildStep methods were invoked in the build phase.

Quarkus indicates the availability of the airhacks-extension after launch (java -jar target/[NAME]-1.0-SNAPSHOT-runner.jar) with a log statement:


2019-06-30 10:47:23,863 INFO  [io.quarkus] (main) Quarkus 0.16.1 started in 0.738s. Listening on: http://[::]:8080
2019-06-30 10:47:23,872 INFO  [io.quarkus] (main) Installed features: [airhacks-extension, cdi, resteasy]

The extension becomes available under: curl http://localhost:8080/airhacks-extension. The first call invokes the servlet's constructor with the debug statement: AirhacksServlet().

The extension mechanism makes the servlet also available for native compilation with mvn clean install -Pnative.

The start by direct calling the binary target/[NAME]-1.0-SNAPSHOT-runner is quicker:


2019-06-30 10:55:19,670 INFO  [io.quarkus] (main) Quarkus 0.16.1 started in 0.085s. Listening on: http://[::]:8080
2019-06-30 10:55:19,672 INFO  [io.quarkus] (main) Installed features: [airhacks-extension, cdi, resteasy]
consumes less memory (around 8MB), but comes with the same behavior.

The sample code is available from: https://github.com/AdamBien/airhacks-quarkus-extension

See you at Web, MicroProfile and Java EE Workshops at Munich Airport, Terminal 2 or Virtual Dedicated Workshops / consulting. Is Munich's airport too far? Learn from home: airhacks.io.