Main Tutorials

Gradle + Quarkus Hello World example

This article shows how to create or scaffold a Gradle + Quarkus JAX-RS hello world project, which creates a /hello endpoint and returns a string.

Technologies used:

  • Quarkus 1.11.0
  • Gradle 6.7
  • Maven 3.6.3
  • Java 11

Topics

  1. Creating a new Gradle + Quartus project
  2. Gradle + Quarkus Project Structure
  3. Quarkus and build.gradle
  4. Quarkus Dependencies (runtimeClasspath)
  5. Quarkus JAX-RX endpoint
  6. Quarkus and Dockerfile
  7. Gradle run Quarkus in Dev Mode
  8. Download Source Code
  9. References

1. Creating a new Gradle + Quartus project

We use the Maven plugin quarkus-maven-plugin and specified an extra option -DbuildTool=gradle to create or scaffold a Gradle + Quarkus project.

1.1 The below command will create a simple Quarkus JAX-RX project.

For Linux and macOS system.

Terminal

mvn io.quarkus:quarkus-maven-plugin:1.11.0.Final:create \
    -DprojectGroupId=com.mkyong \
    -DprojectArtifactId=quarkus-hello-world-gradle \
    -DclassName="com.mkyong.quarkus.HelloResource" \
    -Dpath="/hello"  \
    -DbuildTool=gradle

For Windows, cmd or command prompt, replace the new line \ with a ^.

Terminal

mvn io.quarkus:quarkus-maven-plugin:1.11.0.Final:create ^
    -DprojectGroupId=com.mkyong ^
    -DprojectArtifactId=quarkus-hello-world-gradle ^
    -DclassName="com.mkyong.quarkus.HelloResource" ^
    -Dpath="/hello"  ^
    -DbuildTool=gradle

Output

Terminal

> mvn io.quarkus:quarkus-maven-plugin:1.11.0.Final:create ^
More?     -DprojectGroupId=com.mkyong ^
More?     -DprojectArtifactId=quarkus-hello-world-gradle ^
More?     -DclassName="com.mkyong.quarkus.HelloResource" ^
More?     -Dpath="/hello"  ^
More?     -DbuildTool=gradle
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------< org.apache.maven:standalone-pom >-------------------
[INFO] Building Maven Stub Project (No POM) 1
[INFO] --------------------------------[ pom ]---------------------------------
[INFO]
[INFO] --- quarkus-maven-plugin:1.11.0.Final:create (default-cli) @ standalone-pom ---
-----------

applying codestarts...
? java
? gradle
? quarkus
? config-properties
? dockerfiles
? gradle-wrapper
? resteasy-example

-----------
? quarkus project has been successfully generated in:
--> C:\Users\mkyong\projects\quarkus\quarkus-hello-world-gradle
-----------
[INFO]
[INFO] ========================================================================================
[INFO] Your new application has been created in C:\Users\mkyong\projects\quarkus\quarkus-hello-world-gradle
[INFO] Navigate into this directory and launch your application with mvn quarkus:dev
[INFO] Your application will be accessible on http://localhost:8080
[INFO] ========================================================================================
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  2.095 s
[INFO] Finished at: 2021-01-27T14:32:13+08:00
[INFO] ------------------------------------------------------------------------

2. Gradle + Quarkus Project Structure

The above command created a new project named quarkus-hello-world-gradle, and generates the following files and directories:

  • Standard Maven directory structure.
  • Gradle build.gradle and related wrapper.
  • HelloResource.java for /hello endpoint.
  • Unit Tests.
  • A landing page resources\META-INF\resources\index.html for http://localhost:8080
  • Dockerfile files, for jvm or native mode.
  • The application configuration file, application.properties.

quarkus project structure

Terminal

> cd quarkus-hello-world-gradle

> tree /F
Folder PATH listing
Volume serial number is A446-18E6
C:.
│   .dockerignore
│   .gitignore
│   build.gradle
│   gradle.properties
│   gradlew
│   gradlew.bat
│   README.md
│   settings.gradle
│
├───gradle
│   └───wrapper
│           gradle-wrapper.jar
│           gradle-wrapper.properties
│
└───src
  ├───main
  │   ├───docker
  │   │       Dockerfile.fast-jar
  │   │       Dockerfile.jvm
  │   │       Dockerfile.native
  │   │
  │   ├───java
  │   │   └───com
  │   │       └───mkyong
  │   │           └───quarkus
  │   │                   HelloResource.java
  │   │
  │   └───resources
  │       │   application.properties
  │       │
  │       └───META-INF
  │           └───resources
  │                   index.html
  │
  ├───native-test
  │   └───java
  │       └───com
  │           └───mkyong
  │               └───quarkus
  │                       NativeHelloResourceIT.java
  │
  └───test
      └───java
          └───com
              └───mkyong
                  └───quarkus
                          HelloResourceTest.java

3. Quarkus and build.gradle

Review the Gradle related files: build.gradle, gradle.properties and settings.gradle.

3.1 The project required quarkus-arc for dependency injection; and quarkus-resteasy for JAX-RS endpoint.

build.gradle

plugins {
    id 'java'
    id 'io.quarkus'
}

repositories {
    mavenLocal()
    mavenCentral()
}

dependencies {
    implementation enforcedPlatform("${quarkusPlatformGroupId}:${quarkusPlatformArtifactId}:${quarkusPlatformVersion}")
    implementation 'io.quarkus:quarkus-arc'
    implementation 'io.quarkus:quarkus-resteasy'
    testImplementation 'io.quarkus:quarkus-junit5'
    testImplementation 'io.rest-assured:rest-assured'
}

group 'com.mkyong'
version '1.0.0-SNAPSHOT'

java {
    sourceCompatibility = JavaVersion.VERSION_11
    targetCompatibility = JavaVersion.VERSION_11
}

compileJava {
    options.encoding = 'UTF-8'
    options.compilerArgs << '-parameters'
}

compileTestJava {
    options.encoding = 'UTF-8'
}

3.2 Project properties like Quarkus package and version.

gradle.properties

#Gradle properties
quarkusPluginId=io.quarkus
quarkusPluginVersion=1.11.0.Final
quarkusPlatformGroupId=io.quarkus
quarkusPlatformArtifactId=quarkus-universe-bom
quarkusPlatformVersion=1.11.0.Final

org.gradle.logging.level=INFO

3.3 Project name and plugin info.

settings.gradle

pluginManagement {
    repositories {
        mavenLocal()
        mavenCentral()
        gradlePluginPortal()
    }
    plugins {
        id "${quarkusPluginId}" version "${quarkusPluginVersion}"
    }
}
rootProject.name='quarkus-hello-world-gradle'

4. Quarkus Dependencies (runtimeClasspath)

In Gradle, we can use gradle dependencies --configuration runtimeClasspath to show only the runtime classpath.

Other --configuration options

  • compileClasspath
  • runtimeClasspath
  • testCompileClasspath
  • testCompileClasspath
  • nativeTestCompileClasspath
  • nativeTestRuntimeClasspath

Gradle Quarkus project dependencies

4.1 For a standard Quarkus JAX-RX project, it reuses a lot of proven technologies.

The Quarkus core Technologies:

Terminal

> gradle dependencies --configuration runtimeClasspath

------------------------------------------------------------
Root project
------------------------------------------------------------

runtimeClasspath - Runtime classpath of source set 'main'.
+--- io.quarkus:quarkus-universe-bom:1.11.0.Final
|    +--- io.quarkus:quarkus-arc:1.11.0.Final (c)
|    +--- io.quarkus:quarkus-resteasy:1.11.0.Final (c)
|    +--- io.quarkus.arc:arc:1.11.0.Final (c)
|    +--- io.quarkus:quarkus-core:1.11.0.Final (c)
|    +--- org.eclipse.microprofile.context-propagation:microprofile-context-propagation-api:1.0.1 (c)
|    +--- io.quarkus:quarkus-vertx-http:1.11.0.Final (c)
|    +--- io.quarkus:quarkus-resteasy-server-common:1.11.0.Final (c)
|    +--- jakarta.enterprise:jakarta.enterprise.cdi-api:2.0.2 (c)
|    +--- jakarta.annotation:jakarta.annotation-api:1.3.5 (c)
|    +--- jakarta.transaction:jakarta.transaction-api:1.3.3 (c)
|    +--- org.jboss.logging:jboss-logging:3.4.1.Final (c)
|    +--- jakarta.inject:jakarta.inject-api:1.0 (c)
|    +--- io.quarkus:quarkus-ide-launcher:1.11.0.Final (c)
|    +--- io.quarkus:quarkus-development-mode-spi:1.11.0.Final (c)
|    +--- io.smallrye.config:smallrye-config:1.10.0 (c)
|    +--- org.jboss.logmanager:jboss-logmanager-embedded:1.0.6 (c)
|    +--- org.jboss.logging:jboss-logging-annotations:2.2.0.Final (c)
|    +--- org.jboss.threads:jboss-threads:3.2.0.Final (c)
|    +--- org.slf4j:slf4j-api:1.7.30 (c)
|    +--- org.jboss.slf4j:slf4j-jboss-logmanager:1.1.0.Final (c)
|    +--- org.graalvm.sdk:graal-sdk:20.3.0 (c)
|    +--- org.wildfly.common:wildfly-common:1.5.4.Final-format-001 (c)
|    +--- io.quarkus:quarkus-bootstrap-runner:1.11.0.Final (c)
|    +--- io.quarkus:quarkus-security-runtime-spi:1.11.0.Final (c)
|    +--- io.quarkus:quarkus-vertx-http-dev-console-runtime-spi:1.11.0.Final (c)
|    +--- io.quarkus.security:quarkus-security:1.1.3.Final (c)
|    +--- io.quarkus:quarkus-vertx-core:1.11.0.Final (c)
|    +--- io.vertx:vertx-web:3.9.5 (c)
|    +--- io.quarkus:quarkus-resteasy-common:1.11.0.Final (c)
|    +--- jakarta.validation:jakarta.validation-api:2.0.2 (c)
|    +--- jakarta.interceptor:jakarta.interceptor-api:1.2.5 (c)
|    +--- io.smallrye.common:smallrye-common-annotation:1.5.0 (c)
|    +--- io.smallrye.config:smallrye-config-common:1.10.0 (c)
|    +--- io.smallrye.common:smallrye-common-expression:1.5.0 (c)
|    +--- io.smallrye.common:smallrye-common-constraint:1.5.0 (c)
|    +--- io.smallrye.common:smallrye-common-classloader:1.5.0 (c)
|    +--- io.smallrye.common:smallrye-common-io:1.5.0 (c)
|    +--- io.smallrye.reactive:mutiny:0.12.5 (c)
|    +--- io.quarkus:quarkus-netty:1.11.0.Final (c)
|    +--- io.vertx:vertx-core:3.9.5 (c)
|    +--- io.vertx:vertx-web-common:3.9.5 (c)
|    +--- io.vertx:vertx-auth-common:3.9.5 (c)
|    +--- io.vertx:vertx-bridge-common:3.9.5 (c)
|    +--- org.jboss.resteasy:resteasy-core:4.5.8.SP1 (c)
|    +--- com.sun.activation:jakarta.activation:1.2.1 (c)
|    +--- org.eclipse.microprofile.config:microprofile-config-api:1.4 (c)
|    +--- io.smallrye.common:smallrye-common-function:1.5.0 (c)
|    +--- org.reactivestreams:reactive-streams:1.0.3 (c)
|    +--- io.netty:netty-codec:4.1.49.Final (c)
|    +--- io.netty:netty-handler:4.1.49.Final (c)
|    +--- io.netty:netty-common:4.1.49.Final (c)
|    +--- io.netty:netty-buffer:4.1.49.Final (c)
|    +--- io.netty:netty-transport:4.1.49.Final (c)
|    +--- io.netty:netty-handler-proxy:4.1.49.Final (c)
|    +--- io.netty:netty-codec-http:4.1.49.Final (c)
|    +--- io.netty:netty-codec-http2:4.1.49.Final (c)
|    +--- io.netty:netty-resolver:4.1.49.Final (c)
|    +--- io.netty:netty-resolver-dns:4.1.49.Final (c)
|    +--- com.fasterxml.jackson.core:jackson-core:2.11.3 (c)
|    +--- com.fasterxml.jackson.core:jackson-databind:2.11.3 (c)
|    +--- org.jboss.spec.javax.ws.rs:jboss-jaxrs-api_2.1_spec:2.0.1.Final (c)
|    +--- org.jboss.spec.javax.xml.bind:jboss-jaxb-api_2.3_spec:2.0.0.Final (c)
|    +--- org.jboss.resteasy:resteasy-core-spi:4.5.8.SP1 (c)
|    +--- io.netty:netty-codec-socks:4.1.49.Final (c)
|    +--- io.netty:netty-codec-dns:4.1.49.Final (c)
|    \--- com.fasterxml.jackson.core:jackson-annotations:2.11.3 (c)
+--- io.quarkus:quarkus-arc -> 1.11.0.Final
|    +--- io.quarkus.arc:arc:1.11.0.Final
|    |    +--- jakarta.enterprise:jakarta.enterprise.cdi-api:2.0.2
|    |    |    +--- jakarta.el:jakarta.el-api:3.0.3
|    |    |    +--- jakarta.interceptor:jakarta.interceptor-api:1.2.5
|    |    |    |    \--- jakarta.annotation:jakarta.annotation-api:1.3.5
|    |    |    \--- jakarta.inject:jakarta.inject-api:1.0
|    |    +--- jakarta.annotation:jakarta.annotation-api:1.3.5
|    |    +--- jakarta.transaction:jakarta.transaction-api:1.3.3
|    |    \--- org.jboss.logging:jboss-logging:3.3.2.Final -> 3.4.1.Final
|    +--- io.quarkus:quarkus-core:1.11.0.Final
|    |    +--- jakarta.annotation:jakarta.annotation-api:1.3.5
|    |    +--- jakarta.enterprise:jakarta.enterprise.cdi-api:2.0.2 (*)
|    |    +--- jakarta.inject:jakarta.inject-api:1.0
|    |    +--- io.quarkus:quarkus-ide-launcher:1.11.0.Final
|    |    +--- io.quarkus:quarkus-development-mode-spi:1.11.0.Final
|    |    +--- io.smallrye.config:smallrye-config:1.10.0
|    |    |    +--- io.smallrye.common:smallrye-common-annotation:1.5.0
|    |    |    +--- io.smallrye.config:smallrye-config-common:1.10.0
|    |    |    |    +--- org.eclipse.microprofile.config:microprofile-config-api:1.4
|    |    |    |    +--- io.smallrye.common:smallrye-common-classloader:1.5.0
|    |    |    |    \--- org.jboss.logging:jboss-logging:3.4.1.Final
|    |    |    +--- io.smallrye.common:smallrye-common-expression:1.5.0
|    |    |    |    +--- io.smallrye.common:smallrye-common-function:1.5.0
|    |    |    |    |    \--- io.smallrye.common:smallrye-common-constraint:1.5.0
|    |    |    |    |         \--- org.jboss.logging:jboss-logging:3.4.1.Final
|    |    |    |    \--- org.jboss.logging:jboss-logging:3.4.1.Final
|    |    |    +--- io.smallrye.common:smallrye-common-constraint:1.5.0 (*)
|    |    |    +--- io.smallrye.common:smallrye-common-classloader:1.5.0
|    |    |    \--- org.jboss.logging:jboss-logging:3.4.1.Final
|    |    +--- org.jboss.logging:jboss-logging:3.4.1.Final
|    |    +--- org.jboss.logmanager:jboss-logmanager-embedded:1.0.6
|    |    |    \--- org.wildfly.common:wildfly-common:1.5.0.Final-format-001 -> 1.5.4.Final-format-001
|    |    +--- org.jboss.logging:jboss-logging-annotations:2.2.0.Final
|    |    +--- org.jboss.threads:jboss-threads:3.2.0.Final
|    |    |    +--- org.jboss.logging:jboss-logging:3.4.1.Final
|    |    |    \--- org.wildfly.common:wildfly-common:1.5.0.Final -> 1.5.4.Final-format-001
|    |    +--- org.slf4j:slf4j-api:1.7.30
|    |    +--- org.jboss.slf4j:slf4j-jboss-logmanager:1.1.0.Final
|    |    +--- org.graalvm.sdk:graal-sdk:20.3.0
|    |    +--- org.wildfly.common:wildfly-common:1.5.4.Final-format-001
|    |    \--- io.quarkus:quarkus-bootstrap-runner:1.11.0.Final
|    |         +--- io.smallrye.common:smallrye-common-io:1.5.0
|    |         +--- org.jboss.logmanager:jboss-logmanager-embedded:1.0.5 -> 1.0.6 (*)
|    |         \--- org.jboss.logging:jboss-logging:3.3.2.Final -> 3.4.1.Final
|    \--- org.eclipse.microprofile.context-propagation:microprofile-context-propagation-api:1.0.1
\--- io.quarkus:quarkus-resteasy -> 1.11.0.Final
   +--- io.quarkus:quarkus-vertx-http:1.11.0.Final
   |    +--- io.quarkus:quarkus-core:1.11.0.Final (*)
   |    +--- io.quarkus:quarkus-security-runtime-spi:1.11.0.Final
   |    |    \--- io.quarkus:quarkus-core:1.11.0.Final (*)
   |    +--- io.quarkus:quarkus-vertx-http-dev-console-runtime-spi:1.11.0.Final
   |    |    +--- io.quarkus:quarkus-core:1.11.0.Final (*)
   |    |    +--- io.quarkus.arc:arc:1.11.0.Final (*)
   |    |    \--- io.vertx:vertx-web:3.9.5
   |    |         +--- io.vertx:vertx-web-common:3.9.5
   |    |         |    \--- io.vertx:vertx-core:3.9.5
   |    |         |         +--- io.netty:netty-common:4.1.49.Final
   |    |         |         +--- io.netty:netty-buffer:4.1.49.Final
   |    |         |         |    \--- io.netty:netty-common:4.1.49.Final
   |    |         |         +--- io.netty:netty-transport:4.1.49.Final
   |    |         |         |    +--- io.netty:netty-common:4.1.49.Final
   |    |         |         |    +--- io.netty:netty-buffer:4.1.49.Final (*)
   |    |         |         |    \--- io.netty:netty-resolver:4.1.49.Final
   |    |         |         |         \--- io.netty:netty-common:4.1.49.Final
   |    |         |         +--- io.netty:netty-handler:4.1.49.Final
   |    |         |         |    +--- io.netty:netty-common:4.1.49.Final
   |    |         |         |    +--- io.netty:netty-resolver:4.1.49.Final (*)
   |    |         |         |    +--- io.netty:netty-buffer:4.1.49.Final (*)
   |    |         |         |    +--- io.netty:netty-transport:4.1.49.Final (*)
   |    |         |         |    \--- io.netty:netty-codec:4.1.49.Final
   |    |         |         |         +--- io.netty:netty-common:4.1.49.Final
   |    |         |         |         +--- io.netty:netty-buffer:4.1.49.Final (*)
   |    |         |         |         \--- io.netty:netty-transport:4.1.49.Final (*)
   |    |         |         +--- io.netty:netty-handler-proxy:4.1.49.Final
   |    |         |         |    +--- io.netty:netty-common:4.1.49.Final
   |    |         |         |    +--- io.netty:netty-buffer:4.1.49.Final (*)
   |    |         |         |    +--- io.netty:netty-transport:4.1.49.Final (*)
   |    |         |         |    +--- io.netty:netty-codec:4.1.49.Final (*)
   |    |         |         |    +--- io.netty:netty-codec-socks:4.1.49.Final
   |    |         |         |    |    +--- io.netty:netty-common:4.1.49.Final
   |    |         |         |    |    +--- io.netty:netty-buffer:4.1.49.Final (*)
   |    |         |         |    |    +--- io.netty:netty-transport:4.1.49.Final (*)
   |    |         |         |    |    \--- io.netty:netty-codec:4.1.49.Final (*)
   |    |         |         |    \--- io.netty:netty-codec-http:4.1.49.Final
   |    |         |         |         +--- io.netty:netty-common:4.1.49.Final
   |    |         |         |         +--- io.netty:netty-buffer:4.1.49.Final (*)
   |    |         |         |         +--- io.netty:netty-transport:4.1.49.Final (*)
   |    |         |         |         +--- io.netty:netty-codec:4.1.49.Final (*)
   |    |         |         |         \--- io.netty:netty-handler:4.1.49.Final (*)
   |    |         |         +--- io.netty:netty-codec-http:4.1.49.Final (*)
   |    |         |         +--- io.netty:netty-codec-http2:4.1.49.Final
   |    |         |         |    +--- io.netty:netty-common:4.1.49.Final
   |    |         |         |    +--- io.netty:netty-buffer:4.1.49.Final (*)
   |    |         |         |    +--- io.netty:netty-transport:4.1.49.Final (*)
   |    |         |         |    +--- io.netty:netty-codec:4.1.49.Final (*)
   |    |         |         |    +--- io.netty:netty-handler:4.1.49.Final (*)
   |    |         |         |    \--- io.netty:netty-codec-http:4.1.49.Final (*)
   |    |         |         +--- io.netty:netty-resolver:4.1.49.Final (*)
   |    |         |         +--- io.netty:netty-resolver-dns:4.1.49.Final
   |    |         |         |    +--- io.netty:netty-common:4.1.49.Final
   |    |         |         |    +--- io.netty:netty-buffer:4.1.49.Final (*)
   |    |         |         |    +--- io.netty:netty-resolver:4.1.49.Final (*)
   |    |         |         |    +--- io.netty:netty-transport:4.1.49.Final (*)
   |    |         |         |    +--- io.netty:netty-codec:4.1.49.Final (*)
   |    |         |         |    \--- io.netty:netty-codec-dns:4.1.49.Final
   |    |         |         |         +--- io.netty:netty-common:4.1.49.Final
   |    |         |         |         +--- io.netty:netty-buffer:4.1.49.Final (*)
   |    |         |         |         +--- io.netty:netty-transport:4.1.49.Final (*)
   |    |         |         |         \--- io.netty:netty-codec:4.1.49.Final (*)
   |    |         |         +--- com.fasterxml.jackson.core:jackson-core:2.11.3
   |    |         |         \--- com.fasterxml.jackson.core:jackson-databind:2.11.3
   |    |         |              +--- com.fasterxml.jackson.core:jackson-annotations:2.11.3
   |    |         |              \--- com.fasterxml.jackson.core:jackson-core:2.11.3
   |    |         +--- io.vertx:vertx-auth-common:3.9.5
   |    |         |    \--- io.vertx:vertx-core:3.9.5 (*)
   |    |         +--- io.vertx:vertx-bridge-common:3.9.5
   |    |         \--- io.vertx:vertx-core:3.9.5 (*)
   |    +--- io.quarkus.security:quarkus-security:1.1.3.Final
   |    |    +--- org.jboss.logging:jboss-logging:3.3.2.Final -> 3.4.1.Final
   |    |    \--- io.smallrye.reactive:mutiny:0.4.3 -> 0.12.5
   |    |         +--- org.reactivestreams:reactive-streams:1.0.3
   |    |         \--- io.smallrye.common:smallrye-common-annotation:1.5.0
   |    +--- io.quarkus:quarkus-vertx-core:1.11.0.Final
   |    |    +--- io.quarkus:quarkus-core:1.11.0.Final (*)
   |    |    +--- io.quarkus:quarkus-arc:1.11.0.Final (*)
   |    |    +--- io.quarkus:quarkus-netty:1.11.0.Final
   |    |    |    +--- io.netty:netty-codec:4.1.49.Final (*)
   |    |    |    +--- io.quarkus:quarkus-core:1.11.0.Final (*)
   |    |    |    +--- io.netty:netty-handler:4.1.49.Final (*)
   |    |    |    \--- jakarta.enterprise:jakarta.enterprise.cdi-api:2.0.2 (*)
   |    |    \--- io.vertx:vertx-core:3.9.5 (*)
   |    \--- io.vertx:vertx-web:3.9.5 (*)
   \--- io.quarkus:quarkus-resteasy-server-common:1.11.0.Final
        +--- io.quarkus:quarkus-core:1.11.0.Final (*)
        +--- io.quarkus:quarkus-arc:1.11.0.Final (*)
        +--- io.quarkus:quarkus-resteasy-common:1.11.0.Final
        |    +--- io.quarkus:quarkus-core:1.11.0.Final (*)
        |    +--- org.jboss.resteasy:resteasy-core:4.5.8.SP1
        |    |    +--- org.jboss.spec.javax.ws.rs:jboss-jaxrs-api_2.1_spec:2.0.1.Final
        |    |    +--- org.jboss.spec.javax.xml.bind:jboss-jaxb-api_2.3_spec:1.0.1.Final -> 2.0.0.Final
        |    |    +--- org.jboss.resteasy:resteasy-core-spi:4.5.8.SP1
        |    |    |    +--- org.jboss.spec.javax.ws.rs:jboss-jaxrs-api_2.1_spec:2.0.1.Final
        |    |    |    +--- org.jboss.spec.javax.xml.bind:jboss-jaxb-api_2.3_spec:1.0.1.Final -> 2.0.0.Final
        |    |    |    +--- org.reactivestreams:reactive-streams:1.0.3
        |    |    |    +--- jakarta.validation:jakarta.validation-api:2.0.2
        |    |    |    +--- com.sun.activation:jakarta.activation:1.2.1
        |    |    |    \--- org.jboss.logging:jboss-logging:3.3.2.Final -> 3.4.1.Final
        |    |    +--- org.reactivestreams:reactive-streams:1.0.3
        |    |    +--- jakarta.validation:jakarta.validation-api:2.0.2
        |    |    +--- com.ibm.async:asyncutil:0.1.0
        |    |    +--- com.sun.activation:jakarta.activation:1.2.1
        |    |    +--- org.jboss.logging:jboss-logging:3.3.2.Final -> 3.4.1.Final
        |    |    +--- org.eclipse.microprofile.config:microprofile-config-api:1.4
        |    |    \--- io.smallrye.config:smallrye-config:1.6.1 -> 1.10.0 (*)
        |    +--- io.quarkus:quarkus-arc:1.11.0.Final (*)
        |    \--- com.sun.activation:jakarta.activation:1.2.1
        \--- jakarta.validation:jakarta.validation-api:2.0.2

(c) - dependency constraint
(*) - dependencies omitted (listed previously)

5. Quarkus JAX-RX endpoint

5.1 A default HelloResource.java is generated to provide a /hello endpoint.

HelloResource.java

package com.mkyong.quarkus;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

@Path("/hello")
public class HelloResource {

  @GET
  @Produces(MediaType.TEXT_PLAIN)
  public String hello() {
      return "Hello RESTEasy";
  }
}

5.2 Also a RestAssured unit test for the above endpoint.

HelloResourceTest.java

package com.mkyong.quarkus;

import io.quarkus.test.junit.QuarkusTest;
import org.junit.jupiter.api.Test;

import static io.restassured.RestAssured.given;
import static org.hamcrest.CoreMatchers.is;

@QuarkusTest
public class HelloResourceTest {

  @Test
  public void testHelloEndpoint() {
      given()
        .when().get("/hello")
        .then()
           .statusCode(200)
           .body(is("Hello RESTEasy"));
  }

}

6. Quarkus and Dockerfile

The quarkus-maven-plugin also generates three Dockerfile files to build a Docker container for the JAR file or the native executable.

  1. Dockerfile.fast-jar – Build a docker container for the JAR file, this is a new packaging format (Fast-jar) since Quarkus 1.5 released, for faster startup times.
  2. Dockerfile.jvm – Build a docker container for the JAR file.
  3. Dockerfile.native – Build a docker container for native executable.

6.1 Review the Dockerfile.jvm.

Dockerfile.jvm

####
# This Dockerfile is used in order to build a container that runs the Quarkus application in JVM mode
#
# Before building the container image run:
#
# ./gradlew build
#
# Then, build the image with:
#
# docker build -f src/main/docker/Dockerfile.jvm -t quarkus/quarkus-hello-world-gradle-jvm .
#
# Then run the container using:
#
# docker run -i --rm -p 8080:8080 quarkus/quarkus-hello-world-gradle-jvm
#
# If you want to include the debug port into your docker image
# you will have to expose the debug port (default 5005) like this :  EXPOSE 8080 5050
#
# Then run the container using :
#
# docker run -i --rm -p 8080:8080 -p 5005:5005 -e JAVA_ENABLE_DEBUG="true" quarkus/quarkus-hello-world-gradle-jvm
#
###
FROM registry.access.redhat.com/ubi8/ubi-minimal:8.3

ARG JAVA_PACKAGE=java-11-openjdk-headless
ARG RUN_JAVA_VERSION=1.3.8
ENV LANG='en_US.UTF-8' LANGUAGE='en_US:en'
# Install java and the run-java script
# Also set up permissions for user `1001`
RUN microdnf install curl ca-certificates ${JAVA_PACKAGE} \
    && microdnf update \
    && microdnf clean all \
    && mkdir /deployments \
    && chown 1001 /deployments \
    && chmod "g+rwX" /deployments \
    && chown 1001:root /deployments \
    && curl https://repo1.maven.org/maven2/io/fabric8/run-java-sh/${RUN_JAVA_VERSION}/run-java-sh-${RUN_JAVA_VERSION}-sh.sh -o /deployments/run-java.sh \
    && chown 1001 /deployments/run-java.sh \
    && chmod 540 /deployments/run-java.sh \
    && echo "securerandom.source=file:/dev/urandom" >> /etc/alternatives/jre/lib/security/java.security

# Configure the JAVA_OPTIONS, you can add -XshowSettings:vm to also display the heap size.
ENV JAVA_OPTIONS="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager"
COPY build/lib/* /deployments/lib/
COPY build/*-runner.jar /deployments/app.jar

EXPOSE 8080
USER 1001

ENTRYPOINT [ "/deployments/run-java.sh" ]

6.2 Review the Dockerfile.native.

Dockerfile.native

####
# This Dockerfile is used in order to build a container that runs the Quarkus application in native (no JVM) mode
#
# Before building the container image run:
#
# ./gradlew build -Dquarkus.package.type=native
#
# Then, build the image with:
#
# docker build -f src/main/docker/Dockerfile.native -t quarkus/quarkus-hello-world-gradle .
#
# Then run the container using:
#
# docker run -i --rm -p 8080:8080 quarkus/quarkus-hello-world-gradle
#
###
FROM registry.access.redhat.com/ubi8/ubi-minimal:8.3
WORKDIR /work/
RUN chown 1001 /work \
    && chmod "g+rwX" /work \
    && chown 1001:root /work
COPY --chown=1001:root build/*-runner /work/application

EXPOSE 8080
USER 1001

CMD ["./application", "-Dquarkus.http.host=0.0.0.0"]

7. Gradle run Quarkus in Dev Mode

7.1 In a separated terminal, type command gradlew quarkusDev will run Quarkus application in development mode and by default, enabling hot deployment with background compilation, which means if we modify some code, the changes will automatically take effect.

By default, the Quarkus application starts at port 8080.

Terminal

> gradlew quarkusDev

OpenJDK 64-Bit Server VM warning: forcing TieredStopAtLevel to full optimization because JVMCI is enabled
Listening for transport dt_socket at address: 5005
__  ____  __  _____   ___  __ ____  ______
--/ __ \/ / / / _ | / _ \/ //_/ / / / __/
-/ /_/ / /_/ / __ |/ , _/ ,< / /_/ /\ \
--\___\_\____/_/ |_/_/|_/_/|_|\____/___/
2021-01-27 15:30:16,034 INFO  [io.quarkus] (Quarkus Main Thread) quarkus-hello-world-gradle 1.0.0-SNAPSHOT on JVM
(powered by Quarkus 1.11.0.Final) started in 2.051s. Listening on: http://localhost:8080
2021-01-27 15:30:16,052 INFO  [io.quarkus] (Quarkus Main Thread) Profile dev activated. Live Coding activated.
2021-01-27 15:30:16,053 INFO  [io.quarkus] (Quarkus Main Thread) Installed features: [cdi, resteasy]

<==========---> 80% EXECUTING [3m 16s]                                                                                                                        
> :quarkusDev

7.2 Access the /hello endpoint.

Terminal

> curl http://localhost:8080/hello
Hello RESTEasy

7.3 We modify the /hello endpoint to return a list, and save it.

HelloResource.java

package com.mkyong.quarkus;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import java.util.Arrays;
import java.util.List;

@Path("/hello")
public class HelloResource {

    List<String> list = Arrays.asList("A", "B", "C");

    @GET
    @Produces(MediaType.TEXT_PLAIN)
    public List<String> hello() {
        //return "Hello RESTEasy";
        return list;
    }
}

7.4 Back to the terminal that starts the Quarkus application, the vert.x-worker-thread will detect the changed file and do hot replace automatically.

Terminal

2021-01-27 15:46:18,544 INFO  [io.qua.dep.dev.RuntimeUpdatesProcessor] (vert.x-worker-thread-17) Hot replace total time: 0.484s

7.5 Test the /hello endpoint again.

Terminal

> curl http://localhost:8080/hello
[A, B, C]

7.6 CTRL + C to stop the running Quarkus application.

Download Source Code

$ git clone https://github.com/mkyong/quarkus

$ cd quarkus-hello-world-gradle

$ gradlew quarkusDev

$ curl http://localhost:8080/hello

References

About Author

author image
Founder of Mkyong.com, love Java and open source stuff. Follow him on Twitter. If you like my tutorials, consider make a donation to these charities.

Comments

Subscribe
Notify of
0 Comments
Inline Feedbacks
View all comments