Creating Your First Application
In this guide, you’ll create a REST endpoint, see live coding in action, add a service with dependency injection, and write tests. You won’t write any boilerplate, and you won’t have to restart the app, not even once.
| Already ran the Quick Start? Skip to Using injection. |
1. Prerequisites
To complete this guide, you need:
-
Roughly 15 minutes
-
An IDE
-
JDK 17+ installed with
JAVA_HOMEconfigured appropriately -
Apache Maven 3.9.16
-
Optionally the Quarkus CLI if you want to use it
|
Verify Maven is using the Java you expect
If you have multiple JDK’s installed, it is not certain Maven will pick up the expected java
and you could end up with unexpected results.
You can verify which JDK Maven uses by running |
2. Bootstrapping the project
The easiest way to create a new Quarkus project is to open a terminal and run the following command:
For Windows users:
-
If using cmd, (don’t use backward slash
\and put everything on the same line) -
If using Powershell, wrap
-Dparameters in double quotes e.g."-DprojectArtifactId=getting-started"
It generates the following in ./getting-started:
-
the Maven structure
-
an
org.acme.GreetingResourceREST endpoint exposed on/hello -
an associated unit test
-
a landing page that is accessible on
http://localhost:8080after starting the application -
example
Dockerfilefiles for bothnativeandjvmmodes insrc/main/docker -
the application configuration file
Look at the generated pom.xml.
It imports the Quarkus BOM (quarkus-bom), so you can omit the version of Quarkus dependencies in your project.
It also uses the quarkus-maven-plugin, which is responsible for packaging the application and providing development mode.
2.1. The REST endpoint
During the project creation, the src/main/java/org/acme/GreetingResource.java file has been created with the following content:
package org.acme;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;
@Path("/hello")
public class GreetingResource {
@GET
@Produces(MediaType.TEXT_PLAIN)
public String hello() {
return "Hello from Quarkus REST";
}
}
It’s a very simple REST endpoint, returning "Hello from Quarkus REST" to requests on "/hello".
3. Running the application
Now we are ready to run our application:
quarkus dev
./mvnw quarkus:dev
./gradlew --console=plain quarkusDev
...
__ ____ __ _____ ___ __ ____ ______
--/ __ \/ / / / _ | / _ \/ //_/ / / / __/
-/ /_/ / /_/ / __ |/ , _/ ,< / /_/ /\ \
--\___\_\____/_/ |_/_/|_/_/|_|\____/___/
INFO [io.quarkus] (Quarkus Main Thread) getting-started 1.0.0-SNAPSHOT on JVM (powered by Quarkus {quarkus-version}) started in 0.968s. Listening on: http://localhost:8080
INFO [io.quarkus] (Quarkus Main Thread) Profile dev activated. Live Coding activated.
INFO [io.quarkus] (Quarkus Main Thread) Installed features: [cdi, rest, smallrye-context-propagation, vertx]
Once started, you can request the provided endpoint:
$ curl -w "\n" http://localhost:8080/hello
Hello from Quarkus REST
Keep it running and enjoy the blazing fast hot-reload. If you really want shutdown the application, hit CTRL+C.
|
Automatically add newline with
curl -w "\n"We are using |
4. Live coding
quarkus:dev runs Quarkus in development mode.
Edit your Java files or resource files, save, and refresh your browser, changes take effect immediately, no restart needed.
If there are any issues with compilation or deployment an error page will let you know.
Try it: open src/main/java/org/acme/GreetingResource.java, change "Hello from Quarkus REST" to "Hola from Quarkus", save, and refresh http://localhost:8080/hello.
Then, switch back to "Hello from Quarkus REST", refresh again… changed again!
While dev mode is running, open the Dev UI, a dashboard where you can browse installed extensions, configuration, endpoints, and more, all live-updated as you code.
This will also listen for a debugger on port 5005. If you want to wait for the debugger to attach before running you
can pass -Dsuspend on the command line. If you don’t want the debugger at all you can use -Ddebug=false.
5. Using injection
Dependency injection in Quarkus is based on ArC which is a CDI-based dependency injection solution tailored for Quarkus' architecture. If you’re new to CDI then we recommend you to read the Introduction to CDI guide.
Quarkus only implements a subset of the CDI features and comes with non-standard features and specific APIS, you can learn more about it in the Contexts and Dependency Injection guide.
ArC comes as a dependency of quarkus-rest so you already have it handy.
Let’s modify the application and add a companion bean.
Create the src/main/java/org/acme/GreetingService.java file with the following content:
package org.acme;
import jakarta.enterprise.context.ApplicationScoped;
@ApplicationScoped
public class GreetingService {
public String greeting(String name) {
return "hello " + name;
}
}
Edit the GreetingResource class to inject the GreetingService and create a new endpoint using it:
package org.acme;
import jakarta.inject.Inject;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;
@Path("/hello")
public class GreetingResource {
@Inject
GreetingService service;
@GET
@Produces(MediaType.TEXT_PLAIN)
@Path("/greeting/{name}")
public String greeting(String name) {
return service.greeting(name);
}
@GET
@Produces(MediaType.TEXT_PLAIN)
public String hello() {
return "Hello from Quarkus REST";
}
}
If you stopped the application (keep in mind you don’t have to do it, changes will be automatically deployed by our live reload feature), restart the application with:
quarkus dev
./mvnw quarkus:dev
./gradlew --console=plain quarkusDev
Then check that the endpoint returns hello quarkus as expected:
$ curl -w "\n" http://localhost:8080/hello/greeting/quarkus
hello quarkus
6. Testing
All right, so far so good, but wouldn’t it be better with a few tests, just in case?
In the generated build file, you can see 2 test dependencies:
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>rest-assured</artifactId>
<scope>test</scope>
</dependency>
testImplementation("io.quarkus:quarkus-junit")
testImplementation("io.rest-assured:rest-assured")
Quarkus supports JUnit tests.
Because of this, in the case of Maven, the version of the Surefire Maven Plugin must be set, as the default version does not support JUnit:
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>${surefire-plugin.version}</version>
<configuration>
<argLine>--add-opens java.base/java.lang=ALL-UNNAMED</argLine>
<systemPropertyVariables>
<java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager>
<maven.home>${maven.home}</maven.home>
</systemPropertyVariables>
</configuration>
</plugin>
We also set the java.util.logging system property to make sure tests will use the correct log manager and maven.home to ensure that custom configuration
from ${maven.home}/conf/settings.xml is applied (if any).
The generated project contains a simple test.
Edit the src/test/java/org/acme/GreetingResourceTest.java to match the following content:
package org.acme;
import io.quarkus.test.junit.QuarkusTest;
import org.junit.jupiter.api.Test;
import java.util.UUID;
import static io.restassured.RestAssured.given;
import static org.hamcrest.CoreMatchers.is;
@QuarkusTest (1)
class GreetingResourceTest {
@Test
void testHelloEndpoint() {
given()
.when().get("/hello")
.then()
.statusCode(200) (2)
.body(is("Hello from Quarkus REST"));
}
@Test
void testGreetingEndpoint() {
String uuid = UUID.randomUUID().toString();
given()
.pathParam("name", uuid)
.when().get("/hello/greeting/{name}")
.then()
.statusCode(200)
.body(is("hello " + uuid));
}
}
| 1 | By using the @QuarkusTest annotation, you instruct JUnit to start the application before the tests. |
| 2 | Check the HTTP response status code and content |
These tests use RestAssured, but feel free to use your favorite library.
You can run these using Maven:
./mvnw test
You can also run the test from your IDE directly (be sure you stopped the application first).
By default, tests will run on port 8081 so as not to conflict with the running application. We automatically
configure RestAssured to use this port.
|
If you want to use a different client you should use the
|
The test port can be controlled via the quarkus.http.test-port config property.
6.1. Continuous testing
You can also have Quarkus run your tests automatically as you code.
In the dev mode terminal, press r, and then Quarkus re-runs affected tests on every save, giving you instant feedback without leaving your editor.
See the Continuous Testing guide for more details.
7. Packaging and run the application
The application is packaged using:
quarkus build
./mvnw install
./gradlew build
It produces the quarkus-app directory in /target, which contains the quarkus-run.jar file.
This is a fast-jar, not an über-jar, the dependencies are copied into subdirectories of quarkus-app/lib/.
You can run the application using: java -jar target/quarkus-app/quarkus-run.jar.
If you want to deploy your application somewhere (typically in a container), you need to copy/deploy the whole quarkus-app directory.
|
Before running the application, don’t forget to stop the hot reload mode (hit CTRL+C), or you will have a port conflict.
|
8. What’s next?
You now have a running Quarkus application with dependency injection and tests. Here’s where to go next:
-
Your Second Quarkus Application — add a database without installing one, using Dev Services
-
Building a Native Executable — compile to a native binary and package it in a container
-
Getting Started with Quarkus and Kafka — build event-driven and streaming applications with Quarkus and Apache Kafka
-
Tooling Guide — IDE setup, scaffolding, and development mode tips
8.1. Solution
You can find the completed example in the getting-started directory of the Quarkus quickstarts repository:
git clone https://github.com/quarkusio/quarkus-quickstarts.git