Package for running on a JVM or natively

In this chapter, we explain how to package a Quarkus CXF application for running on a JVM or for running it natively.

JVM mode

In the introductory guides for SOAP client and SOAP service, we worked only in Quarkus dev mode: Quarkus tooling was running on the background, watching for changes in our workspace, recompiling and reloading the application as needed.

How do we run the application on a JVM once we are done with the development?

First we need to package it with Maven:

$ mvn package

The libraries needed to run the application on a JVM can be found in target/quarkus-app directory:

$ ls -lh target/quarkus-app
drwxr-xr-x. 2 ppalaga ppalaga 4.0K Jan 12 22:29 app
drwxr-xr-x. 4 ppalaga ppalaga 4.0K Jan 12 22:29 lib
drwxr-xr-x. 2 ppalaga ppalaga 4.0K Jan 12 22:29 quarkus
-rw-r-r--. 1 ppalaga ppalaga 6.1K Jan 12 22:29 quarkus-app-dependencies.txt
-rw-r-r--. 1 ppalaga ppalaga  678 Jan 12 22:29 quarkus-run.jar

We can start the application as follows:

$ java -jar target/quarkus-app/quarkus-run.jar

You can send some SOAP requests using curl to make sure that the application works.

Native mode

Quarkus offers first class support for building GraalVM native images and Quarkus CXF fully honors that promise too.


GraalVM native images are platform specific executable files that you can run directly without a JVM. They boot faster and spend less memory compared to running the same application in JVM mode.

The pom.xml file generated by contains the native profile needed for building the native image:


Further, as mentioned in the Create a new project section, you need the GraalVM native-image tool.

You should either have it installed locally and have GRAALVM_HOME environment variable set properly, or — if you only need to produce a Linux native executable — you can use docker.

With local installation of GraalVM
# Make sure $GRAALVM_HOME is set properly

# Produce the native executable
mvn package -Pnative

Quarkus is quite picky about the GraalVM version. When using the local installation, always make sure that you use the version preferred by Quarkus. You can do that by opening quarkus-bom imported in your pom.xml and searching for graalvm there. If you use Docker, Quarkus takes care for pulling the right version for you.

With docker
# Produce the native executable
mvn package -Pnative -Dquarkus.native.container-build=true

This can take a minute or so for a simple application.

When the build is done, the native executable should be available in target directory:

$ ls -l target
-rwxr-xr-x. 1 ppalaga ppalaga  71M Jan 11 22:42 quarkus-cxf-integration-test-server-1.8.0-SNAPSHOT-runner

As you can see, it has a size of only 71 MB, and is executable.

You can run it as follows:

$ target/*-runner
INFO  [io.quarkus] (main) quarkus-cxf-integration-test-server 1.8.0-SNAPSHOT native (powered by Quarkus
2.15.2.Final) started in 0.042s. Listening on:

Again, you can send some SOAP requests using curl to make sure that the native executable works.

Do not forget to compare the memory usage, time to first request and other performance metrics with the stack you used before and share your results!

Create container image

Refer to Quarkus Container image guide.