SlideShare a Scribd company logo
Quarkus Cheat-Sheet
What is Quarkus?
Quarkus is a Kubernetes Native Java stack tailored for GraalVM &
OpenJDK HotSpot, crafted from the best of breed Java libraries and
standards. Also focused on developer experience, making things
just work with little to no con guration and allowing to do live
coding.
Cheat-sheet tested with Quarkus 2.7.0.Final.
Getting Started
Quarkus comes with a Maven archetype to scaffold a very simple
starting project.
mvn io.quarkus:quarkus-maven-plugin:2.7.0.Final:create 
-DprojectGroupId=org.acme 
-DprojectArtifactId=getting-started 
-DclassName="org.acme.quickstart.GreetingResource" 
-Dpath="/hello"
This creates a simple JAX-RS resource called GreetingResource.
@Path("/hello")
public class GreetingResource {
@GET
@Produces(MediaType.TEXT_PLAIN)
public String hello() {
return "hello";
}
}
Gradle
There is no way to scaffold a project in Gradle but you only need to
do:
plugins {
id 'java'
id 'io.quarkus' version '0.26.1'
}
repositories {
mavenCentral()
}
dependencies {
implementation enforcedPlatform('io.quarkus:quarkus-bo
m:0.26.1')
implementation 'io.quarkus:quarkus-resteasy'
}
Or in Kotlin:
plugins {
java
}
apply(plugin = "io.quarkus")
repositories {
mavenCentral()
}
dependencies {
implementation(enforcedPlatform("io.quarkus:quarkus-bo
m:0.26.1"))
implementation("io.quarkus:quarkus-resteasy")
}
Packaging
mvn clean package
You need to distribute the -runner.jar le together with quarkus-
app directory.
If quarkus.package.uber-jar property is set to true, then a uber-jar is
created with all dependencies bundled inside the JAR.
By default, Quarkus uses fast jar packaging, if quarkus.package.type
property is set to legacy-jar then Quarkus creates the old standard
jar le.
application.properties
quarkus.package.uber-jar=true
quarkus.package.type=legacy-jar
To compile to native, you need to set GRAALVM_HOME environment
variable and run the native pro le.
mvn clean package -Pnative
./gradlew build -Dquarkus.package.type=native
Possible quarkus.package.type are: jar, legacy-jar, uber-jar and
native.
AppCDS
Automatically generate AppCDS as part of the build process set the
next property: quarkus.package.create-appcds=true.
To make use of it, just run java -jar -XX:SharedArchiveFile=app-
cds.jsa myapp.jar.
Command mode
You can de ne the main CLI method to start Quarkus. There are two
ways, implementing io.quarkus.runtime.QuarkusApplication
interface or use the Java main method to launch Quarkus.
@io.quarkus.runtime.annotations.QuarkusMain
public class HelloWorldMain implements QuarkusApplication {
@Override
public int run(String... args) throws Exception {
System.out.println("Hello World");
return 10;
}
}
run method called when Quarkus starts, and stops when it nishes.
As Java main:
@QuarkusMain
public class JavaMain {
public static void main(String... args) {
Quarkus.run(HelloWorldMain.class, args);
}
}
Use @QuarkusMain in only one place.
Use Quarkus.waitForExit() from the main thread if you want to run
some logic on startup, and then run like a normal application (i.e.
not exit).
You can inject command line arguments by using
@CommandLineArguments annotation:
@CommandLineArguments
String[] args;
Testing
Command Mode applications can be tested using the
@QuarkusMainTest and @QuarkusMainIntegrationTest annotations.
import io.quarkus.test.junit.main.Launch;
import io.quarkus.test.junit.main.LaunchResult;
import io.quarkus.test.junit.main.QuarkusMainLauncher;
import io.quarkus.test.junit.main.QuarkusMainTest;
@QuarkusMainTest
public class HelloTest {
@Test
@Launch("World")
public void testLaunchCommand(LaunchResult result) {
Assertions.assertEquals("Hello World", result.getOu
tput());
}
@Test
@Launch(value = {}, exitCode = 1)
public void testLaunchCommandFailed() {
}
@Test
public void testManualLaunch(QuarkusMainLauncher launch
er) {
LaunchResult result = launcher.launch("Everyone");
Assertions.assertEquals(0, result.exitCode());
Assertions.assertEquals("Hello Everyone", result.ge
tOutput());
}
}
Picocli
You can use Picocli to implement CLI applications:
./mvnw quarkus:add-extension
-Dextensions="picocli"
@CommandLine.Command
public class HelloCommand implements Runnable {
@CommandLine.Option(names = {"-n", "--name"}, descripti
on = "Who will we greet?", defaultValue = "World")
String name;
private final GreetingService greetingService;
public HelloCommand(GreetingService greetingService) {
this.greetingService = greetingService;
}
@Override
public void run() {
greetingService.sayHello(name);
}
}
All classes annotated with picocli.CommandLine.Command are
registered as CDI beans.
If only one class annotated with picocli.CommandLine.Command it will
be used as entry point. If you want to provide your own
@QuarkusMain
@CommandLine.Command(name = "demo", mixinStandardHelpOption
s = true)
public class ExampleApp implements Runnable, QuarkusApplica
tion {
@Inject
CommandLine.IFactory factory;
@Override
public void run() {
}
@Override
public int run(String... args) throws Exception {
return new CommandLine(this, factory).execute(arg
s);
}
}
Use quarkus.picocli.native-image.processing.enable to false to use
the picocli-codegen annotation processor instead of build steps.
You can also con gure CDI beans with PicoCLI arguments:
@CommandLine.Command
public class EntryCommand implements Runnable {
@CommandLine.Option(names = "-c", description = "JDBC c
onnection string")
String connectionString;
@Inject
DataSource dataSource;
}
@ApplicationScoped
class DatasourceConfiguration {
@Produces
@ApplicationScoped
DataSource dataSource(CommandLine.ParseResult parseResu
lt) {
System.out.println(parseResult.matchedOption("c").g
etValue().toString());
}
}
Extensions
Quarkus comes with extensions to integrate with some libraries
such as JSON-B, Camel or MicroPro le spec. To list all available
extensions just run:
./mvnw quarkus:list-extensions
You can use -DsearchPattern=panache to lter out all
extensions except the ones matching the expression.
And to register the extensions into build tool:
./mvnw quarkus:add-extension -Dextensions=""
./mvnw quarkus:remove-extension -Dextensions=""
extensions property supports CSV format to register more
than one extension at once.
Application Lifecycle
You can be noti ed when the application starts/stops by observing
StartupEvent and ShutdownEvent events.
@ApplicationScoped
public class ApplicationLifecycle {
void onStart(@Observes StartupEvent event) {}
void onStop(@Observes ShutdownEvent event) {}
}
Quarkus supports graceful shutdown. By default there is no timeout
but can be set by using the quarkus.shutdown.timeout con g
property.
Dev Mode
./mvnw compile quarkus:dev
./gradlew quarkusDev
Endpoints are registered automatically to provide some basic
debug info in dev mode:
HTTP GET /quarkus/arc/beans
Query Parameters: scope, beanClass, kind.
HTTP GET /quarkus/arc/observers
Dev Services
Quarkus supports the automatic provisioning of uncon gured
services in development and test mode.
General con guration properties:
quarkus.devservices.enabled
If you want to disable all Dev Services. (default: true)
quarkus.devservices.timeout
Startup timeout. (default: 60S)
Set DOCKER_HOST env var to a remote Docker Host to use it instead
the local one.
Dev UI
Quarkus adds a Dev UI console to expose extension features.
The Dev UI is available in dev mode only and accessible at the
/q/dev endpoint by default.
Continuous Testing
Quarkus supports continuous testing, where tests run immediately
after code changes have been saved. This allows you to get instant
feedback on your code changes. Quarkus detects which tests cover
which code, and uses this information to only run the relevant tests
when code is changed.
Start Quarkus in Dev Mode to run it.
Also, you can start continuous testing and not dev mode by running
mvn quarkus:test.
quarkus.test.exclude-pattern
Tests that should be excluded with continuous testing default:
.*.IT[^.]+|.*IT|.*ITCase
Adding Con guration Parameters
To add con guration to your application, Quarkus relies on
MicroPro le Con g spec.
@ConfigProperty(name = "greetings.message")
String message;
@ConfigProperty(name = "greetings.message",
defaultValue = "Hello")
String messageWithDefault;
@ConfigProperty(name = "greetings.message")
Optional<String> optionalMessage;
Properties can be set (in decreasing priority) as:
System properties (-Dgreetings.message).
Environment variables (GREETINGS_MESSAGE).
Environment le named .env placed in the current working
directory (GREETING_MESSAGE=).
External con g directory under the current working directory:
config/application.properties.
Resources src/main/resources/application.properties.
greetings.message = Hello World
Array, List and Set are supported. The delimiter is comma
(,) char and  is the escape char.
Con guration Pro les
Quarkus allow you to have multiple con guration in the same le
(application.properties).
The syntax for this is %{profile}.config.key=value.
quarkus.http.port=9090
%dev.quarkus.http.port=8181
HTTP port will be 9090, unless the 'dev' pro le is active.
Default pro les are:
dev: Activated when in development mode (quarkus:dev).
test: Activated when running tests.
prod: The default pro le when not running in development or
test mode
You can create custom pro le names by enabling the pro le either
setting quarkus.profile system property or QUARKUS_PROFILE
environment variable.
quarkus.http.port=9090
%staging.quarkus.http.port=9999
And enable it quarkus.profile=staging.
To get the active pro le programmatically use
io.quarkus.runtime.configuration.ProfileManager.getActiveProfile().
You can also set it in the build tool:
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>${surefire-plugin.version}</version>
<configuration>
<systemPropertyVariables>
<quarkus.test.profile>foo</quarkus.test.profile>
<buildDirectory>${project.build.directory}
</buildDirectory>
</systemPropertyVariables>
</configuration>
Same for maven-failsafe-plugin.
test {
useJUnitPlatform()
systemProperty "quarkus.test.profile", "foo"
}
Special properties are set in prod mode:
quarkus.application.version and quarkus.application.name to get
them available at runtime.
@ConfigProperty(name = "quarkus.application.name")
String applicationName;
Additional locations
You can use smallrye.config.locations property to set additional
con guration les.
smallrye.config.locations=config.properties
or
java -jar -Dsmallrye.config.locations=config.properties
You can embed con guration les inside a dependency by adding
META-INF/microprofile.properties inside the JAR. When dependency
is added to the application, con guration properties are merged
with current con guration.
@Con gProperties
As an alternative to injecting multiple related con guration values,
you can also use the @io.quarkus.arc.config.ConfigProperties
annotation to group properties.
@ConfigProperties(prefix = "greeting", namingStrategy=Namin
gStrategy.KEBAB_CASE)
public class GreetingConfiguration {
private String message;
// getter/setter
}
This class maps greeting.message property de ned in
application.properties.
You can inject this class by using CDI @Inject GreetingConfiguration
greeting;.
@IfBuildProfile, @UnlessBuildProfile, @IfBuildProperty and
@UnlessBuildProperty annotations are used to de ne when
con guration properties are valid.
@UnlessBuildProfile("test")
@ConfigProperties
public class ServiceConfiguration {
public String user;
public String password;
}
Also you can use an interface approach:
@ConfigProperties(prefix = "greeting", namingStrategy=Namin
gStrategy.KEBAB_CASE)
public interface GreetingConfiguration {
@ConfigProperty(name = "message")
String message();
String getSuffix();
If property does not follow getter/setter naming convention you
need to use org.eclipse.microprofile.config.inject.ConfigProperty
to set it.
Nested objects are also supporte:
@ConfigProperties(prefix = "greeting", namingStrategy=Namin
gStrategy.KEBAB_CASE)
public class GreetingConfiguration {
public String message;
public HiddenConfig hidden;
public static class HiddenConfig {
public List<String> recipients;
}
}
And an application.properties mapping previous class:
greeting.message = hello
greeting.hidden.recipients=Jane,John
Bean Validation is also supported so properties are validated at
startup time, for example @Size(min = 20) public String message;.
prefix attribute is not mandatory. If not provided, attribute
is determined by class name (ie GreeetingConfiguration is
translated to greeting or GreetingExtraConfiguration to
greeting-extra). The su x of the class is always removed.
Naming strategy can be changed with property namingStrategy.
KEBAB_CASE (whatever.foo-bar) or VERBATIM (whatever.fooBar).
@io.quarkus.arc.config.ConfigIgnore annotation can be used to
ignore the injection of con guration elements.
@ConfigIgnore
public Integer ignored;
YAML Con g
YAML con guration is also supported. The con guration le is
called application.yaml and you need to register a dependency to
enable its support:
pom.xml
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-config-yaml</artifactId>
</dependency>
quarkus:
datasource:
url: jdbc:postgresql://localhost:5432/some-database
driver: org.postgresql.Driver
Or with pro les:
"%dev":
quarkus:
datasource:
url: jdbc:postgresql://localhost:5432/some-database
driver: org.postgresql.Driver
In case of subkeys ~ is used to refer to the unpre xed part.
quarkus:
http:
cors:
~: true
methods: GET,PUT,POST
Is equivalent to:
quarkus.http.cors=true
quarkus.http.cors.methods=GET,PUT,POST
Custom Loader
You can implement your own ConfigSource to load con guration
from different places than the default ones provided by Quarkus.
For example, database, custom XML, REST Endpoints, …
You need to create a new class and implement ConfigSource
interface:
package com.acme.config;
public class InMemoryConfig implements ConfigSource {
private Map<String, String> prop = new HashMap<>();
public InMemoryConfig() {
// Init properties
}
@Override
public int getOrdinal() {
// The highest ordinal takes precedence
return 900;
}
@Override
public Map<String, String> getProperties() {
return prop;
}
@Override
public String getValue(String propertyName) {
return prop.get(propertyName);
}
@Override
public String getName() {
return "MemoryConfigSource";
}
}
Then you need to register the ConfigSource as Java service. Create
a le with the following content:
/META-INF/services/org.eclipse.microprofile.config.spi.ConfigSource
com.acme.config.InMemoryConfig
Custom Converters
You can implement your own conversion types from String.
Implement org.eclipse.microprofile.config.spi.Converter
interface:
@Priority(DEFAULT_QUARKUS_CONVERTER_PRIORITY + 100)
public class CustomInstantConverter
implements Converter<Instant> {
@Override
public Instant convert(String value) {
if ("now".equals(value.trim())) {
return Instant.now();
}
return Instant.parse(value);
}
}
@Priority annotation is used to override the default
InstantConverter.
Then you need to register the Converter as Java service. Create a
le with the following content:
/META-INF/services/org.eclipse.microprofile.config.spi.Converter
com.acme.config.CustomInstantConverter
Undertow Properties
Possible parameters with pre x quarkus.servlet:
context-path
The context path to serve all Servlet context from. (default: /)
default-charset
The default charset to use for reading and writing requests.
(default: UTF-8)
Injection
Quarkus is based on CDI 2.0 to implement injection of code. It is
not fully supported and only a subset of the speci cation is
implemented.
@ApplicationScoped
public class GreetingService {
public String message(String message) {
return message.toUpperCase();
}
}
Scope annotation is mandatory to make the bean discoverable.
@Inject
GreetingService greetingService;
Quarkus is designed with Substrate VM in mind. For this
reason, we encourage you to use package-private scope
instead of private.
Produces
You can also create a factory of an object by using
@javax.enterprise.inject.Produces annotation.
@Produces
@ApplicationScoped
Message message() {
Message m = new Message();
m.setMsn("Hello");
return m;
}
@Inject
Message msg;
Quali ers
You can use quali ers to return different implementations of the
same interface or to customize the con guration of the bean.
@Qualifier
@Retention(RUNTIME)
@Target({TYPE, METHOD, FIELD, PARAMETER})
public @interface Quote {
@Nonbinding String value();
}
@Produces
@Quote("")
Message message(InjectionPoint msg) {
Message m = new Message();
m.setMsn(
msg.getAnnotated()
.getAnnotation(Quote.class)
.value()
);
return m;
}
@Inject
@Quote("Aloha Beach")
Message message;
Quarkus breaks the CDI spec by allowing you to inject
quali ed beans without using @Inject annotation.
@Quote("Aloha Beach")
Message message;
Quarkus breaks the CDI spec by skipping the @Produces
annotation completely if the producer method is annotated
with a scope annotation, a stereotype or a quali er.
@Quote("")
Message message(InjectionPoint msg) {
}
@Quote("Aloha Beach")
Message message;
@LookupIfProperty indicates that a bean should only be obtained if a
runtime con guration property matches the provided value.
@LookupUnlessProperty, on the other hand, indicates that a bean
should only be obtained if a runtime con guration property does
not match the provided value.
@LookupIfProperty(name = "service.foo.enabled", stringValue
= "true")
@ApplicationScoped
class ServiceFoo implements Service {
public String name() {
return "foo";
}
}
Alternatives
It is also possible to select alternatives for an application using
application.properties.
quarkus.arc.selected-alternatives=org.acme.Foo,org.acme.*,B
ar
Beans by Quarkus Pro le
Using @io.quarkus.arc.profile.IfBuildProfile and
@io.quarkus.arc.profile.UnlessBuildProfile annotations, you can
conditionally enable a bean.
@Dependent
public class TracerConfiguration {
@Produces
@IfBuildProfile("prod")
public Tracer realTracer(Reporter reporter, Configurati
on configuration) {
return new RealTracer(reporter, configuration);
}
@Produces
@DefaultBean
public Tracer noopTracer() {
return new NoopTracer();
}
}
Using @io.quarkus.arc.profile.IfBuildProperty annotation, you can
conditionally enable a bean. @io.quarkus.arc.DefaultBean sets the
default bean.
@Dependent
public class TracerConfiguration {
@Produces
@IfBuildProperty(name = "some.tracer.enabled", stringVa
lue = "true")
public Tracer realTracer(Reporter reporter, Configurati
on configuration) {}
@Produces
@DefaultBean
public Tracer noopTracer() {}
}
Properties set at runtime have absolutely no effect on the
bean resolution using @IfBuildProperty.
Container-managed Concurrency
Quarkus provides @io.quarkus.arc.Lock and a built-in interceptor for
concurrency control.
@Lock
@ApplicationScoped
class SharedService {
void addAmount(BigDecimal amout) {
}
@Lock(value = Lock.Type.READ, time = 1, unit = TimeUni
t.SECONDS)
BigDecimal getAmount() {
}
}
By default the class is in write mode (so no concurrent calls
allowed) except when lock type is READ where the method can be
called concurrently if no write operation in process.
JSON Marshalling/Unmarshalling
To work with JSON-B you need to add a dependency:
./mvnw quarkus:add-extension
-Dextensions="io.quarkus:quarkus-resteasy-jsonb"
Any POJO is marshaled/unmarshalled automatically.
public class Sauce {
private String name;
private long scovilleHeatUnits;
// getter/setters
}
JSON equivalent:
{
"name":"Blair's Ultra Death",
"scovilleHeatUnits": 1100000
}
In a POST endpoint example:
@POST
@Consumes(MediaType.APPLICATION_JSON)
public Response create(Sauce sauce) {
// Create Sauce
return Response.created(URI.create(sauce.getId()))
.build();
}
To provide custom JsonBCon g object:
@Dependent
JsonbConfig jsonConfig(Instance<JsonbConfigCustomizer> cust
omizers) {
JsonbConfig config = myJsonbConfig(); // Custom `JsonbC
onfig`
for (JsonbConfigCustomizer customizer : customizers) {
customizer.customize(config);
}
return config;
}
To work with Jackson you need to add:
./mvnw quarkus:add-extension
-Dextensions="quarkus-resteasy-jackson"
If you don’t want to use the default ObjectMapper you can customize
it by:
@ApplicationScoped
public class CustomObjectMapperConfig {
@Singleton
@Produces
public ObjectMapper objectMapper(Instance<ObjectMapperC
ustomizer> customizers) {
ObjectMapper objectMapper = new ObjectMapper();
// perform configuration
for (ObjectMapperCustomizer customizer : customizer
s) {
customizer.customize(mapper);
}
return objectMapper;
}
}
Default media type in Quarkus RestEasy is JSON.
XML Marshalling/Unmarshalling
To work with JAX-B you need to add a dependency:
./mvnw quarkus:add-extension
-Dextensions="quarkus-resteasy-jaxb"
Then annotated POJOs are converted to XML.
@XmlRootElement
public class Message {
}
@GET
@Produces(MediaType.APPLICATION_XML)
public Message hello() {
return message;
}
JAXP
To work with JAX-P you need to add a dependency:
./mvnw quarkus:add-extension
-Dextensions="jaxp"
final DocumentBuilder dBuilder = DocumentBuilderFactory.new
Instance().newDocumentBuilder();
final Document doc = dBuilder.parse(in);
return doc.getDocumentElement().getTextContent();
Validator
Quarkus uses Hibernate Validator to validate input/output of REST
services and business services using Bean validation spec.
./mvnw quarkus:add-extension
-Dextensions="io.quarkus:quarkus-hibernate-validator"
Annotate POJO objects with validator annotations such as:
@NotNull, @Digits, @NotBlank, @Min, @Max, …
public class Sauce {
@NotBlank(message = "Name may not be blank")
private String name;
@Min(0)
private long scovilleHeatUnits;
// getter/setters
}
To validate an object use @Valid annotation:
public Response create(@Valid Sauce sauce) {}
If a validation error is triggered, a violation report is
generated and serialized as JSON. If you want to
manipulate the output, you need to catch in the code the
ConstraintViolationException exception.
Create Your Custom Constraints
First you need to create the custom annotation:
@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR,
PARAMETER, TYPE_USE })
@Retention(RUNTIME)
@Documented
@Constraint(validatedBy = { NotExpiredValidator.class})
public @interface NotExpired {
String message() default "Sauce must not be expired";
Class<?>[] groups() default { };
Class<? extends Payload>[] payload() default { };
}
You need to implement the validator logic in a class that
implements ConstraintValidator.
public class NotExpiredValidator
implements ConstraintValidator<NotExpired, LocalDate>
{
@Override
public boolean isValid(LocalDate value,
ConstraintValidatorContext ctx) {
if ( value == null ) return true;
LocalDate today = LocalDate.now();
return ChronoUnit.YEARS.between(today, value) > 0;
}
}
And use it normally:
@NotExpired
@JsonbDateFormat(value = "yyyy-MM-dd")
private LocalDate expired;
Manual Validation
You can call the validation process manually instead of relaying to
@Valid by injecting Validator class.
@Inject
Validator validator;
And use it:
Set<ConstraintViolation<Sauce>> violations =
validator.validate(sauce);
Localization
You can con gure the based locale for validation messages.
quarkus.default-locale=ca-ES
# Supported locales resolved by Accept-Language
quarkus.locales=en-US,es-ES,fr-FR, ca_ES
ValidationMessages_ca_ES.properties
pattern.message=No conforme al patro
@Pattern(regexp = "A.*", message = "{pattern.message}")
private String name;
Bean Validation can be con gured . The pre x is:
quarkus.hibernate-validator.
fail-fast
When fail fast is enabled the validation will stop on the rst
constraint violation detected. (default: false)
method-validation.allow-overriding-parameter-constraints
De ne whether overriding methods that override constraints
should throw an exception. (default: false).
method-validation.allow-parameter-constraints-on-parallel-methods
De ne whether parallel methods that de ne constraints should
throw an exception. (default: false).
method-validation.allow-multiple-cascaded-validation-on-return-
values
De ne whether more than one constraint on a return value may
be marked for cascading validation are allowed. (default: false).
Logging
You can con gure how Quarkus logs:
quarkus.log.console.enable=true
quarkus.log.console.level=DEBUG
quarkus.log.console.color=false
quarkus.log.category."com.lordofthejars".level=DEBUG
Pre x is quarkus.log.
category."<category-name>".level
Minimum level category (default: INFO)
level
Default minimum level (default: INFO)
console.enabled
Console logging enabled (default: true)
console.format
Format pattern to use for logging. Default value:
%d{yyyy-MM-dd HH:mm:ss,SSS} %-5p [%c{3.}] (%t) %s%e%n
console.level
Minimum log level (default: INFO)
console.color
Allow color rendering (default: true)
console.stderr
If console logging should go to System#err instead of
System#out (default: false)
file.enable
File logging enabled (default: false)
file.format
Format pattern to use for logging. Default value:
%d{yyyy-MM-dd HH:mm:ss,SSS} %h %N[%i] %-5p [%c{3.}] (%t) %s%e%n
file.level
Minimum log level (default: ALL)
file.path
The path to log le (default: quarkus.log)
file.rotation.max-file-size
The maximum le size of the log le
file.rotation.max-backup-index
The maximum number of backups to keep (default: 1)
file.rotation.file-suffix
Rotating log le su x.
file.rotation.rotate-on-boot
Indicates rotate logs at bootup (default: true)
file.async
Log asynchronously (default: false)
file.async.queue-length
The queue length to use before ushing writing (default: 512)
file.async.overflow
Action when queue is full (default: BLOCK)
syslog.enable
syslog logging is enabled (default: false)
syslog.format
The format pattern to use for logging to syslog. Default value:
%d{yyyy-MM-dd HH:mm:ss,SSS} %h %N[%i] %-5p [%c{3.}] (%t) %s%e%n
syslog.level
The minimum log level to write to syslog (default: ALL)
syslog.endpoint
The IP address and port of the syslog server (default:
localhost:514)
syslog.app-name
The app name used when formatting the message in RFC5424
format (default: current process name)
syslog.hostname
The name of the host the messages are being sent from (default:
current hostname)
syslog.facility
Priority of the message as de ned by RFC-5424 and RFC-3164
(default: USER_LEVEL)
syslog.syslog-type
The syslog type of format message (default: RFC5424)
syslog.protocol
Protocol used (default: TCP)
syslog.use-counting-framing
Message pre xed with the size of the message (default false)
syslog.truncate
Message should be truncated (default: true)
syslog.block-on-reconnect
Block when attempting to reconnect (default: true)
syslog.async
Log asynchronously (default: false)
syslog.async.queue-length
The queue length to use before ushing writing (default: 512)
syslog.async.overflow
Action when queue is full (default: BLOCK)
You can inject logger instance:
import org.jboss.logging.Logger;
import io.quarkus.arc.log.LoggerName;
@Inject
Logger log;
@LoggerName("foo")
Logger fooLog;
public void ping() {
log.info("Simple!");
}
Gelf ouput
You can con gure the output to be in GELF format instead of plain
text.
./mvnw quarkus:add-extension
-Dextensions="quarkus-logging-gelf"
handler.gelf.enabled
Enable GELF logging handler (default: false)
handler.gelf.host
Hostname/IP of Logstash/Graylof. Prepend tcp: for using TCP
protocol. (default: udp:localhost)
handler.gelf.port
The port. (default: 12201)
handler.gelf.version
GELF version. (default: 1.1)
handler.gelf.extract-stack-trace
Post Stack-Trace to StackTrace eld. (default: true)
handler.gelf.stack-trace-throwable-reference
Gets the cause level to stack trace. 0 is fulls tack trace. (default:
0)
handler.gelf.filter-stack-trace
Stack-Trace ltering. (default: false)
handler.gelf.timestamp-pattern
Java Date pattern. (default: yyyy-MM-dd HH:mm:ss,SSS)
handler.gelf.level
Log level java.util.logging.Level. (default: ALL)
handler.gelf.facility
Name of the facility. (default: jboss-logmanage)
handler.gelf.additional-field.<field>.<subfield>
Post additional elds. quarkus.log.handler.gelf.additional-
field.field1.type=String
handler.gelf.include-full-mdc
Include all elds from the MDC.
handler.gelf.maximum-message-size
Maximum message size (in bytes). (default: 8192)
handler.gelf.include-log-message-parameters
Include message parameters from the log event. (default: true)
handler.gelf.include-location
Include source code location. (default: true)
JSON output
You can con gure the output to be in JSON format instead of plain
text.
./mvnw quarkus:add-extension
-Dextensions="quarkus-logging-json"
And the con guration values are pre x with quarkus.log:
json
JSON logging is enabled (default: true).
json.pretty-print
JSON output is "pretty-printed" (default: false)
json.date-format
Specify the date format to use (default: the default format)
json.record-delimiter
Record delimiter to add (default: no delimiter)
json.zone-id
The time zone ID
json.exception-output-type
The exception output type: detailed, formatted, detailed-and-
formatted (default: detailed)
json.print-details
Detailed caller information should be logged (default: false)
Rest Client
Quarkus implements MicroPro le Rest Client spec:
./mvnw quarkus:add-extension
-Dextensions="quarkus-rest-client"
To get content from http://worldclockapi.com/api/json/cet/now
you need to create a service interface:
@Path("/api")
@RegisterRestClient
public interface WorldClockService {
@GET @Path("/json/cet/now")
@Produces(MediaType.APPLICATION_JSON)
WorldClock getNow();
@GET
@Path("/json/{where}/now")
@Produces(MediaType.APPLICATION_JSON)
WorldClock getSauce(@BeanParam
WorldClockOptions worldClockOptions);
}
public class WorldClockOptions {
@HeaderParam("Authorization")
String auth;
@PathParam("where")
String where;
}
And con gure the hostname at application.properties:
org.acme.quickstart.WorldClockService/mp-rest/url=
http://worldclockapi.com
Injecting the client:
@RestClient
WorldClockService worldClockService;
If invokation happens within JAX-RS, you can propagate headers
from incoming to outgoing by using next property.
org.eclipse.microprofile.rest.client.propagateHeaders=
Authorization,MyCustomHeader
You can still use the JAX-RS client without any problem
ClientBuilder.newClient().target(…)
Adding headers
You can customize the headers passed by implementing
MicroPro le ClientHeadersFactory annotation:
@RegisterForReflection
public class BaggageHeadersFactory
implements ClientHeadersFactory {
@Override
public MultivaluedMap<String, String> update(
MultivaluedMap<String, String> incomingHeaders,
MultivaluedMap<String, String> outgoingHeaders) {}
}
And registering it in the client using RegisterClientHeaders
annotation.
@RegisterClientHeaders(BaggageHeadersFactory.class)
@RegisterRestClient
public interface WorldClockService {}
Or statically set:
@GET
@ClientHeaderParam(name="X-Log-Level", value="ERROR")
Response getNow();
Asynchronous
A method on client interface can return a CompletionStage class to
be executed asynchronously.
@GET @Path("/json/cet/now")
@Produces(MediaType.APPLICATION_JSON)
CompletionStage<WorldClock> getNow();
Reactive
Rest Client also integrates with reactive library named Mutiny. To
start using it you need to add the quarkus-rest-client-mutiny.
After that, a methodon a client interface can return a
io.smallrye.mutiny.Uni instance.
@GET @Path("/json/cet/now")
@Produces(MediaType.APPLICATION_JSON)
Uni<WorldClock> getNow();
A RESTEasy Reactive-based REST Client extension. You only need
to replace the quarkus-rest-client to quarkus-rest-client-reactive.
Multipart
It is really easy to send multipart form-data with Rest Client.
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-multipart-provider</artifactId>
</dependency>
The model object:
import java.io.InputStream;
import javax.ws.rs.FormParam;
import javax.ws.rs.core.MediaType;
import
org.jboss.resteasy.annotations.providers.multipart.Part
Type;
public class MultipartBody {
@FormParam("file")
@PartType(MediaType.APPLICATION_OCTET_STREAM)
private InputStream file;
@FormParam("fileName")
@PartType(MediaType.TEXT_PLAIN)
private String name;
// getter/setters
}
And the Rest client interface:
import
org.jboss.resteasy.annotations.providers.multipart.Mult
ipartForm;
@Path("/echo")
@RegisterRestClient
public interface MultipartService {
@POST
@Consumes(MediaType.MULTIPART_FORM_DATA)
@Produces(MediaType.TEXT_PLAIN)
String sendMultipartData(@MultipartForm
MultipartBody data);
}
SSL
You can con gure Rest Client key stores.
org.acme.quickstart.WorldClockService/mp-rest/trustStore=
classpath:/store.jks
org.acme.quickstart.WorldClockService/mp-rest/trustStorePas
sword=
supersecret
Possible con guration properties:
%s/mp-rest/trustStore
Trust store location de ned with classpath: or file: pre x.
%s/mp-rest/trustStorePassword
Trust store password.
%s/mp-rest/trustStoreType
Trust store type (default: JKS)
%s/mp-rest/hostnameVerifier
Custom hostname veri er class name. To disable SSL veri cation
you can use io.quarkus.restclient.NoopHostnameVerifier.
%s/mp-rest/keyStore
Key store location de ned with classpath: or file: pre x.
%s/mp-rest/keyStorePassword
Key store password.
%s/mp-rest/keyStoreType
Key store type (default: JKS)
Timeout
You can de ne the timeout of the Rest Client:
org.acme.quickstart.WorldClockService/mp-rest/connectTimeou
t=
1000
org.acme.quickstart.WorldClockService/mp-rest/readTimeout=
2000
Instantiate client programmatically
MovieReviewService reviewSvc = RestClientBuilder.newBuilder
()
.baseUri(apiUri)
.build(WorldClockService.class);
Testing
Quarkus archetype adds test dependencies with JUnit 5 and Rest-
Assured library to test REST endpoints.
@QuarkusTest
public class GreetingResourceTest {
@Test
public void testHelloEndpoint() {
given()
.when().get("/hello")
.then()
.statusCode(200)
.body(is("hello"));
}
}
Test port can be set in quarkus.http.test-port property. Timeout
can be set in quarkus.http.test-timeout property.
You can also inject the URL where Quarkus is started:
@TestHTTPResource("index.html")
URL url;
@TestHTTPEndpoint(GreetingResource.class)
@TestHTTPResource
URL url;
@QuarkusTest
@TestHTTPEndpoint(GreetingResource.class)
public class GreetingResourceTest {
@Test
public void testHelloEndpoint() {
given()
.when().get()
.then()
.statusCode(200)
.body(is("hello"));
}
}
Root path is calculated automatically, not necessary to explicitly
set.
If you want any changes made to be rolled back at the end ofthe
test you can use the io.quarkus.test.TestTransaction annotation.
QuarkusTestPro le
You can de ne for each Test class a different con guration options.
This implies that the Quarkus service is restarted.
public class MyProfile implements io.quarkus.test.junit.Qua
rkusTestProfile {
@Override
public Map<String, String> getConfigOverrides() {
return Map.of("greetings.message", "This is a Test"
);
}
@Override
public String getConfigProfile() {
return "my-test-profile";
}
@Override
public Set<String> tags() {
return Collections.singleton("test1");
}
}
@QuarkusTest
@TestProfile(MyProfile.class)
public class MyTestClass {
}
quarkus.test.profile.tags property can be set to limit test
execution of test pro les. If not set all tests are executed.
quarkus.test.profile.tags=test1
Quarkus Test Resource
You can execute some logic before the rst test run (start) and
execute some logic at the end of the test suite (stop).
You need to create a class implementing
QuarkusTestResourceLifecycleManager interface and register it in the
test via @QuarkusTestResource annotation.
public class MyCustomTestResource
implements QuarkusTestResourceLifecycleManager {
@Override
public Map<String, String> start() {
// return system properties that
// should be set for the running test
return Collections.emptyMap();
}
@Override
public void stop() {
}
// optional
@Override
public void inject(Object testInstance) {
}
// optional
@Override
public int order() {
return 0;
}
// optional
@Override
public void setContext(Context context) {
}
@Override
public void inject(TestInjector testInjector) {
testInjector.injectIntoFields(wireMockServer,
new TestInjector.AnnotatedAndMatchesType(Inject
WireMock.class, WireMockServer.class));
}
}
public class MyTest {
@InjectWireMock
WireMockServer wireMockServer;
}
Returning new system properties implies running parallel
tests in different JVMs.
And the usage:
@QuarkusTestResource(MyCustomTestResource.class)
public class MyTest {
}
When using multiple QuarkusTestResource you can set parallel
attribute to true to start them concurrently.
Testing Callbacks
You can enrich all your @QuarkusTest classes by implementing the
following callback interfaces:
io.quarkus.test.junit.callback.QuarkusTestBeforeClassCallback
io.quarkus.test.junit.callback.QuarkusTestAfterConstructCall
back
io.quarkus.test.junit.callback.QuarkusTestBeforeEachCallback
io.quarkus.test.junit.callback.QuarkusTestAfterEachCallback
public class SimpleAnnotationCheckerBeforeClassCallback imp
lements QuarkusTestBeforeClassCallback {
@Override
public void beforeClass(Class<?> testClass) {
}
}
And needs to be registered as Java SPI:
META-
INF/services/io.quarkus.test.junit.callback.QuarkusTestBeforeClassCallback
io.quarkus.it.main.SimpleAnnotationCheckerBeforeClassCallba
ck
Mocking
If you need to provide an alternative implementation of a service
(for testing purposes) you can do it by using CDI @Alternative
annotation using it in the test service placed at src/test/java:
@Alternative
@Priority(1)
@ApplicationScoped
public class MockExternalService extends ExternalService {}
This does not work when using native image testing.
A stereotype annotation io.quarkus.test.Mock is provided declaring
@Alternative, @Priority(1) and @Dependent.
Mockito
Instead of creating stubs, you can also create mocks of your
services with mockito Add the following dependency
io.quarkus:quarkus-junit5-mockito:
@InjectMock
GreetingService greetingService;
@BeforeEach
public void setup() {
Mockito.when(greetingService.greet()).thenReturn("Hi");
}
@Path("/hello")
public class ExampleResource {
@Inject
GreetingService greetingService;
}
Mock is automatically injected and only valid for the de ned test
class.
@InjectMock has convertScopes parameter that if true, then Quarkus
will change the scope of the target from Singleton bean to
ApplicationScoped to make the mockable.
Also spy is supported:
@InjectSpy
GreetingService greetingService;
Mockito.verify(greetingService, Mockito.times(1)).greet();
REST Client
To Mock REST Client, you need to de ne the interface with
@ApplicationScope:
@ApplicationScoped
@RegisterRestClient
public interface GreetingService {
}
@InjectMock
@RestClient
GreetingService greetingService;
Mockito.when(greetingService.hello()).thenReturn("hello fro
m mockito");
Interceptors
Tests are actually full CDI beans, so you can apply CDI interceptors:
@QuarkusTest
@Stereotype
@Transactional
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface TransactionalQuarkusTest {
}
@TransactionalQuarkusTest
public class TestStereotypeTestCase {}
Decorator
Quarkus also supports CDI Decorators:
@Priority(10)
@Decorator
public class LargeTxAccount implements Account {
@Inject
@Any
@Delegate
Account delegate;
@Inject
LogService logService;
void withdraw(BigDecimal amount) {
delegate.withdraw(amount);
if (amount.compareTo(1000) > 0) {
logService.logWithdrawal(delegate, amount);
}
}
}
Test Coverage
Due the nature of Quarkus to calculate correctly the coverage
information with JaCoCo, you might need o ine instrumentation.
./mvnw quarkus:add-extension
-Dextensions="quarkus-jacoco "
Possible con guration parameters pre xed quarkus.jacoco:
data-file
The jacoco data le. (default: jacoco-quarkus.exec)
report
If Quarkus should generate the Jacoco report. (default: true)
output-encoding
Encoding of the generated reports. (default: UTF-8)
title
Name of the root node HTML report pages.
footer
Footer text used in HTML report pages.
source-encoding
Encoding of the source les. (default: UTF-8)
includes
A list of class les to include in the report. (default: **)
excludes
A list of class les to exclude from the report.
report-location
The location of the report les. (default: jacoco-report)
Native Testing
To test native executables annotate the test with @NativeImageTest.
Quarkus Integration Tests
@QuarkusIntegrationTest should be used to launch and test the
artifact produced by the Quarkus build. If the result of a Quarkus
build is a JAR then the app is launched as java -jar, if native is
launched as ./application, if container image is created (JiB,
Docker extensions) is launched as docker run.
You can connect to already running application by using the
following properties: quarkus.http.test-host=1.2.3.4
quarkus.http.test-port=4321
Persistence
Quarkus works with JPA(Hibernate) as persistence solution. But
also provides an Active Record pattern implementation under
Panache project.
To use database access you need to add Quarkus JDBC drivers
instead of the original ones. At this time Apache Derby, H2, MariaDB,
MySQL, MSSQL and PostgreSQL drivers are supported.
./mvnw quarkus:add-extension
-Dextensions="io.quarkus:quarkus-hibernate-orm-panache,
io.quarkus:quarkus-jdbc-mariadb"
@Entity
public class Developer extends PanacheEntity {
// id field is implicit
public String name;
}
And con guration in src/main/resources/application.properties:
quarkus.datasource.jdbc.url=jdbc:mariadb://localhost:3306/m
ydb
quarkus.datasource.db-kind=mariadb
quarkus.datasource.username=developer
quarkus.datasource.password=developer
quarkus.hibernate-orm.database.generation=update
List of datasource parameters.
quarkus.datasource as pre x is skipped in the next table.
db-kind
Built-in datasource kinds so the JDBC driver is resolved
automatically. Possible values: derby, h2, mariadb, mssql, mysql,
postgresql, db2.
username
Username to access.
password
Password to access.
driver
JDBC Driver class. It is not necessary to set if db-kind used.
credentials-provider
Sets a custom credential provider name.
credentials-provider-name
It is the @Named value of the credentials provider bean. Not
necessary if only one implementation.
jdbc.url
The datasource URL.
jdbc.min-size
The datasource pool minimum size. (default: 0)
jdbc.max-size
The datasource pool maximum size. (default: 20)
jdbc.initial-size
The initial size of the pool.
jdbc.background-validation-interval
The interval at which we validate idle connections in the
background. (default: 2M)
jdbc.acquisition-timeout
The timeout before cancelling the acquisition of a new
connection. (default: 5)
jdbc.leak-detection-interval
The interval at which we check for connection leaks.
jdbc.idle-removal-interval
The interval at which we try to remove idle connections. (default:
5M)
jdbc.max-lifetime
The max lifetime of a connection.
jdbc.transaction-isolation-level
The transaction isolation level. Possible values: UNDEFINED, NONE,
READ_UNCOMMITTED, READ_COMMITTED, REPEATABLE_READ, SERIALIZABLE.
jdbc.detect-statement-leaks
Warn when a connection is returned to the pool without the
application having closed all open statements. (default: true)
jdbc.new-connection-sql
Query executed when rst using a connection.
jdbc.validation-query-sql
Query executed to validate a connection.
jdbc.pooling-enabled
Disable pooling to prevent reuse of Connections. (default: true)
jdbc.enable-metrics
Enable datasource metrics collection when using quarkus-
smallrye-metrics extension.
jdbc.additional-jdbc-properties.<extraProperty>
Unspeci ed properties to be passed to the JDBC driver when
creating new connections.
Hibernate con guration properties. Pre x quarkus.hibernate-orm is
skipped.
dialect
Class name of the Hibernate ORM dialect.
dialect.storage-engine
The storage engine when the dialect supports multiple storage
engines.
sql-load-script
Name of the le containing the SQL statements to execute when
starts. no-file force Hibernate to skip SQL import. (default:
import.sql)
batch-fetch-size
The size of the batches. (default: -1 disabled)
maxFetchDepth
The maximum depth of outer join fetch tree for single-ended
associations.
multitenant
De nes the method for multi-tenancy. Possible values: DATABASE,
NONE, SCHEMA. (default: NONE)
multitenant-schema-datasource
De nes the name of the data source to use in case of SCHEMA
approach.
metadata-builder-contributor
Class name of a custom
org.hibernate.boot.spi.MetadataBuilderContributor
implementation.
query.query-plan-cache-max-size
The maximum size of the query plan cache.
query.default-null-ordering
Default precedence of null values in ORDER BY. Possible values:
none, first, last. (default: none)
database.generation
Database schema is generation. Possible values: none, create,
drop-and-create, drop, update. (default: none)
database.generation.halt-on-error
Stop on the rst error when applying the schema. (default: false)
database.generation.create-schemas
Hibernate ORM should create the schemas automatically (for
databases supporting them).
database.default-catalog
Default catalog.
database.default-schema
Default Schema.
database.charset
Charset.
scripts.generation
Select whether the database schema DDL les are generated or
not. Possible values: none, create, drop-and-create, drop, update.
(default: none)
scripts.generation.create-target
Filename or URL where the database create DDL le should be
generated.
scripts.generation.drop-target
Filename or URL where the database drop DDL le should be
generated.
jdbc.timezone
Time Zone JDBC driver.
jdbc.statement-fetch-size
Number of rows fetched at a time.
jdbc.statement-batch-size
Number of updates sent at a time.
log.sql
Show SQL logs (default: false)
log.jdbc-warnings
statistics
Enable statiscs collection. (default: false)
physical-naming-strategy
Class name of the Hibernate PhysicalNamingStrategy
implementation.
globally-quoted-identifiers
Should quote all identi ers. (default: false)
metrics-enabled
Metrics published with smallrye-metrics extension (default:
false)
second-level-caching-enabled
Enable/Disable 2nd level cache. (default: true)
Database operations:
// Insert
Developer developer = new Developer();
developer.name = "Alex";
developer.persist();
// Find All
Developer.findAll().list();
// Hibernate Filters
Person.findAll().filter("Person.hasName", Parameters.with(
"name", "Alex"));
// Find By Query
Developer.find("name", "Alex").firstResult();
// Delete
Developer developer = new Developer();
developer.id = 1;
developer.delete();
Person.deleteById(id);
// Delete By Query
long numberOfDeleted = Developer.delete("name", "Alex");
Remember to annotate methods with @Transactional annotation to
make changes persisted in the database.
If queries start with the keyword from then they are treated as HQL
query, if not then next short form is supported:
order by which expands to from EntityName order by …
<columnName> which expands to from EntityName where
<columnName>=?
<query> which is expanded to from EntityName where <query>
Static Methods
findById: Object
Returns object or null if not found. Overloaded version with
LockModeType is provided.
findByIdOptional: Optional<Object>
Returns object or java.util.Optional.
find: String, [Object…, Map<String, Object>, Parameters]
Lists of entities meeting given query with parameters set.
Returning a PanacheQuery.
find: String, Sort, [Object…, Map<String, Object>, Parameters]
Lists of entities meeting given query with parameters set sorted
by Sort attribute/s. Returning a PanacheQuery.
findAll
Finds all entities. Returning a PanacheQuery.
findAll: Sort
Finds all entities sorted by Sort attribute/s. Returning a
PanacheQuery.
list: String, [Object…, Map<String, Object>, Parameters]
Lists of entities meeting given query with parameters set.
Returning a List.
list: String, Sort, [Object…, Map<String, Object>, Parameters]
Lists of entities meeting given query with parameters set sorted
by Sort attribute/s. Returning a List.
listAll
Finds all entities. Returning a List.
listAll: Sort
Finds all entities sorted by Sort attribute/s. Returning a List.
stream: String, [Object…, Map<String, Object>, Parameters]
java.util.stream.Stream of entities meeting given query with
parameters set.
stream: String, Sort, [Object…, Map<String, Object>, Parameters]
java.util.stream.Stream of entities meeting given query with
parameters set sorted by Sort attribute/s.
streamAll
java.util.stream.Stream of all entities.
streamAll: Sort
java.util.stream.Stream of all entities sorted by Sort attribute/s.
count
Number of entities.
count: String, [Object…, Map<String, Object>, Parameters]
Number of entities meeting given query with parameters set.
Enables a Hibernate lter during fetching of results for this query.
deleteAll
Number of deleted entities.
delete: String, [Object…, Map<String, Object>, Parameters]
Number of deleted entities meeting given query with parameters
set.
deleteById: boolean, [Object]
Delete by id. Returns if deleted or not.
persist: [Iterable, Steram, Object…]
Persist object.
In case of using streams, remember to close them or use a
try/catch block: try (Stream<Person> persons = Person.streamAll()).
find methods de nes a withLock(LockModeType) to de ne
the lock type and withHint(QueryHints.HINT_CACHEABLE,
"true") to de ne hints.
Named Queries
@Entity
@NamedQuery(name = "Person.getByName", query = "from Person
where name = :name")
public class Person extends PanacheEntity {
public static Person findByName(String name){
return find("#Person.getByName", name).firstResult
();
}
}
Pagination
PanacheQuery<Person> livingPersons = Person
.find("status", Status.Alive);
livingPersons.page(Page.ofSize(25));
// get the first page
List<Person> firstPage = livingPersons.list();
// get the second page
List<Person> secondPage = livingPersons.nextPage().list();
Range
PanacheQuery<Person> livingPersons = Person
.find("status", Status.Alive);
List<Person> secondRange = livingPersons.range(25, 49).list
();
You cannot mix pagination and range.
If entities are de ned in external JAR, you need to enable in these
projects the Jandex plugin in project.
<plugin>
<groupId>org.jboss.jandex</groupId>
<artifactId>jandex-maven-plugin</artifactId>
<version>1.0.3</version>
<executions>
<execution>
<id>make-index</id>
<goals>
<goal>jandex</goal>
</goals>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>org.jboss</groupId>
<artifactId>jandex</artifactId>
<version>2.1.1.Final</version>
</dependency>
</dependencies>
</plugin>
Panache includes an annotation processor that enhance your
entities If you disable annotation processors you might need to
create a marker le on Panache archives at META-INF/panache-
archive.marker manually.
Testing
To mock using active record pattern:
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-panache-mock</artifactId>
<scope>test</scope>
</dependency>
@Test
public void testPanacheMocking() {
PanacheMock.mock(Person.class);
Mockito.when(Person.count()).thenReturn(23l);
Assertions.assertEquals(23, Person.count());
PanacheMock.verify(Person.class, Mockito.times(1)).coun
t();
}
DevServices
When testing or running in dev mode Quarkus can even provide you
with a zero con g database out of the box. Depending on your
database type you may need docker installed in order to use this
feature.
The following open source databases:
Postgresql (container)
MySQL (container)
MariaDB (container)
H2 (in-process)
Apache Derby (in-process)
To use DevServices don’t con gure a database URL, username and
password, Quarkus will provide the database and you can just start
coding without worrying about con g.
quarkus.datasource.db-kind=mariadb
%prod.quarkus.datasource.jdbc.url=jdbc:mariadb://db:3306/my
db
%prod.quarkus.datasource.username=developer
%prod.quarkus.datasource.password=developer
Possible con guration values pre xed with quarkus.datasource:
devservices
If devservices is enabled or not. (default: true)
devservices.image-name
The container image name to use instead of the default one.
devservices.properties
Generic properties that are added to the database connection
URL.
DAO pattern
Also supports DAO pattern with PanacheRepository<TYPE>.
@ApplicationScoped
public class DeveloperRepository
implements PanacheRepository<Person> {
public Person findByName(String name){
return find("name", name).firstResult();
}
}
EntityManager You can inject EntityManager in your classes:
@Inject
EntityManager em;
@Inject
org.hibernate.Session session;
@Inject
org.hibernate.SessionFactory sessionFactory;
em.persist(car);
Multiple datasources
You can register more than one datasource.
# default
quarkus.datasource.db-kind=h2
quarkus.datasource.jdbc.url=jdbc:h2:tcp://localhost/mem:def
ault
....
# users datasource
quarkus.datasource.users.devservices=false
quarkus.datasource.users.db-kind=h2
quarkus.datasource.users.jdbc.url=jdbc:h2:tcp://localhost/m
em:users
Notice that after datasource you set the datasource name, in
previous case users.
You can inject then AgroalDataSource with
io.quarkus.agroal.DataSource.
@DataSource("users")
AgroalDataSource dataSource1;
Flushing
You can force ush operation by calling .flush() or
persistAndFlush() to make it in a single call
This ush is less e cient and you still need to commit
transaction.
Testing
There is a Quarkus Test Resource that starts and stops H2 server
before and after test suite.
Register dependency io.quarkus:quarkus-test-h2:test.
And annotate the test:
@QuarkusTestResource(H2DatabaseTestResource.class)
public class FlywayTestResources {
}
Transactions
The easiest way to de ne your transaction boundaries is to use the
@Transactional annotation.
Transactions are mandatory in case of none idempotent
operations.
@Transactional
public void createDeveloper() {}
You can control the transaction scope:
@Transactional(REQUIRED) (default): starts a transaction if none
was started, stays with the existing one otherwise.
@Transactional(REQUIRES_NEW): starts a transaction if none was
started; if an existing one was started, suspends it and starts a
new one for the boundary of that method.
@Transactional(MANDATORY): fails if no transaction was started ;
works within the existing transaction otherwise.
@Transactional(SUPPORTS): if a transaction was started, joins it ;
otherwise works with no transaction.
@Transactional(NOT_SUPPORTED): if a transaction was started,
suspends it and works with no transaction for the boundary of
the method; otherwise works with no transaction.
@Transactional(NEVER): if a transaction was started, raises an
exception; otherwise works with no transaction.
You can con gure the default transaction timeout using
quarkus.transaction-manager.default-transaction-timeout
con guration property. By default it is set to 60 seconds.
You can set a timeout property, in seconds, that applies to
transactions created within the annotated method by using
@TransactionConfiguration annotation.
@Transactional
@TransactionConfiguration(timeout=40)
public void createDeveloper() {}
If you want more control over transactions you can inject
UserTransaction and use a programmatic way.
@Inject UserTransaction transaction
transaction.begin();
transaction.commit();
transaction.rollback();
You can implement your custom credentials provider (ie Azure
KeyVault) to provide a username/password for the database
connection. Name information is not necessary if there is only one
custom credential provider.
@ApplicationScoped
@Unremovable
@Named("my-credentials-provider")
public class CustomCredentialsProvider implements Credentia
lsProvider {
@Inject
Config config;
@Override
public Properties getCredentials(String credentials
ProviderName) {
properties.put(CredentialsProvider.USER_PROPERTY_NA
ME, "hibernate_orm_test");
properties.put(CredentialsProvider.PASSWORD
_PROPERTY_NAME, "hibernate_orm_test");
}
}
quarkus.datasource.credentials-provider=
custom
quarkus.datasource.credentials-provider-name=
my-credentials-provider
Hibernate Multitenancy
Multitenancy is supported using Schema or Database approach.
First you need to de ne how tenant is identi ed:
@RequestScoped
@Unremovable
public class CustomTenantResolver implements TenantResolver
{
@Inject
RoutingContext context;
@Override
public String getDefaultTenantId() {
return "base";
}
@Override
public String resolveTenantId() {
}
}
Schema approach
quarkus.hibernate-orm.database.generation=none
quarkus.hibernate-orm.multitenant=SCHEMA
Database approach
quarkus.hibernate-orm.database.generation=none
quarkus.hibernate-orm.multitenant=DATABASE
# default tenant
quarkus.datasource.base.db-kind=postgresql
quarkus.datasource.base.username=quarkus_test
...
# Tenant 'mycompany'
quarkus.datasource.mycompany.db-kind=postgresql
quarkus.datasource.mycompany.username=mycompany
quarkus.flyway.mycompany.locations=classpath:database/mycom
pany
...
If you need more dynamic approach implement: @ApplicationScoped
io.quarkus.hibernate.orm.runtime.tenant.TenantConnectionResolver
Hibernate Envers
Quarkus supports Hibernate Envers.
./mvnw quarkus:add-extension
-Dextensions="hibernate-envers"
Con guration properties pre xed with quarkus.hibernate-envers:
store-data-at-delete
Enable store_data_at_delete feature. (default: false)
audit-table-suffix
De nes a su x for historical data table. (default: _AUD)
audit-table-prefix
De nes a pre x for historical data table. (default: ``)
revision-field-name
Revision eld name. (default: REV)
revision-type-field-name
Revision type eld name. (default: REVTYPE)
REST Data Panache
REST Data with Panache extension can generate the basic CRUD
endpoints for your entities and repositories.
./mvnw quarkus:add-extension
-Dextensions="hibernate-orm-rest-data-panache"
You also need to add the JDBC driver extension and a JSON
Marshaller (ie resteasy-jackson).
Then you can de ne interfaces for de ning endpoints:
In case of Active Record pattern:
public interface DeveloperResource extends PanacheEntityRes
ource<Developer, Long> {
}
In case of Repository:
public interface DeveloperResource extends PanacheRepositor
yResource<DeveloperRepository, Developer, Long> {
}
Quarkus will generate automatically the implementation for you
following the next rules:
Default path is a hyphenated lowercase resource name
without a su x of resource or controller.
get(@PathParam("id")), list, add(Developer),
update(@PathParam("id"), Developer), delete(@PathParam("id"))
You can customize these defaults by using @ResourceProperties and
@MethodProperties annotations.
@ResourceProperties(hal = true, path = "my-developer", halC
ollectionName = "dev-collections")
public interface DeveloperResource extends PanacheEntityRes
ource<Developer, Long> {
@MethodProperties(path = "all")
List<Developer> list();
@MethodProperties(exposed = false)
void delete(Long id);
}
If hal is true, you need to send the Accept: application/hal+json
HTTP header to get the response.
Hibernate Reactive
./mvnw quarkus:add-extension
-Dextensions="quarkus-hibernate-reactive, quarkus-resteas
y-mutiny, "
Also you need to add the reactive driver (ie quarkus-reactive-pg-
client).
You can use: org.hibernate.reactive.mutiny.Mutiny or
org.hibernate.reactive.stage.Stage.
@Entity
@Table(name = "dev")
public class Developer {
}
@Inject
CompletionStage<Stage.Session> stageSession;
@Inject
Uni<Mutiny.Session> mutinySession;
public Uni<Long> reactivePersist() {
return mutinySession
.flatMap(s -> s.persist(new Developer(1, "Alex"))
.flatMap(v -> session.flush())
....
}
public CompletionStage<Developer> reactiveFind() {
return stageSession
.thenCompose(session -> {
session.find(Developer.class, 1);
});
}
In nispan
Quarkus integrates with In nispan:
./mvnw quarkus:add-extension
-Dextensions="infinispan-client"
Serialization uses a library called Protostream.
Annotation based
@ProtoFactory
public Author(String name, String surname) {
this.name = name;
this.surname = surname;
}
@ProtoField(number = 1)
public String getName() {
return name;
}
@ProtoField(number = 2)
public String getSurname() {
return surname;
}
Initializer to set con guration settings.
@AutoProtoSchemaBuilder(includeClasses =
{ Book.class, Author.class },
schemaPackageName = "book_sample")
interface BookContextInitializer
extends SerializationContextInitializer {
}
User written based
There are three ways to create your schema:
Proto le
Creates a .proto le in the META-INF directory.
package book_sample;
message Author {
required string name = 1;
required string surname = 2;
}
In case of having a Collection eld you need to use the repeated key
(ie repeated Author authors = 4).
In code
Setting proto schema directly in a produced bean.
@Produces
FileDescriptorSource bookProtoDefinition() {
return FileDescriptorSource
.fromString("library.proto",
"package book_sample;n" +
"message Author {n" +
" required string name = 1;n" +
" required string surname = 2;n" +
"}");
}
Marshaller
Using org.infinispan.protostream.MessageMarshaller interface.
public class AuthorMarshaller
implements MessageMarshaller<Author> {
@Override
public String getTypeName() {
return "book_sample.Author";
}
@Override
public Class<? extends Author> getJavaClass() {
return Author.class;
}
@Override
public void writeTo(ProtoStreamWriter writer,
Author author) throws IOException {
writer.writeString("name", author.getName());
writer.writeString("surname", author.getSurname());
}
@Override
public Author readFrom(ProtoStreamReader reader)
throws IOException {
String name = reader.readString("name");
String surname = reader.readString("surname");
return new Author(name, surname);
}
}
And producing the marshaller:
@Produces
MessageMarshaller authorMarshaller() {
return new AuthorMarshaller();
}
In nispan Embedded
./mvnw quarkus:add-extension
-Dextensions="infinispan-embeddedy"
Con guration in infinispan.xml:
<local-cache name="quarkus-transaction">
<transaction
transaction-manager-lookup=
"org.infinispan.transaction.lookup.JBossStandaloneJ
TAManagerLookup"/>
</local-cache>
Set con guration le location in application.properties:
quarkus.infinispan-embedded.xml-config=infinispan.xml
And you can inject the main entry point for the cache:
@Inject
org.infinispan.manager.EmbeddedCacheManager cacheManager;
DevServices
When testing or running in dev mode Quarkus can even provide you
with a zero con g In nispan out of the box.
Possible con guration values pre xed with quarkus.infinispan-
client:
devservices.enabled
If devservices is enabled or not. (default: true)
devservices.port
Optional xed port the dev service will listen to. If not de ned, the
port will be chosen randomly.
devservices.shared
Indicates if the In nispan managed by Quarkus Dev Services is
shared. When shared, Quarkus looks for running containers using
label-based service discovery. (default: true)
devservices.service-name
The value of the quarkus-dev-service-infinispan label attached to
the started container. (default: infinispan)
devservices.artifacts
List of the artifacts to automatically download and add to the
In nispan server libraries.
Redis
Quarkus integrates with Redis.
./mvnw quarkus:add-extension
-Dextensions="redis-client"
Con gure Redis location:
quarkus.redis.hosts=localhost:6379
You can use synchronous or reactive clients:
@Inject
RedisClient redisClient;
@Inject
ReactiveRedisClient reactiveRedisClient;
void increment(String key, Integer incrementBy) {
redisClient.incrby(key, incrementBy.toString());
}
Uni<List<String>> keys() {
return reactiveRedisClient
.keys("*")
.map(response -> {
List<String> result = new ArrayList<>();
for (Response r : response) {
result.add(r.toString());
}
return result;
});
}
DevServices
When testing or running in dev mode Quarkus can even provide you
with a zero con g Redis out of the box.
Possible con guration values pre xed with quarkus.redis:
devservices.enabled
If devservices is enabled or not. (default: true)
devservices.image-name
The container image name to use instead of the default one.
devservices.port
Optional xed port the dev service will listen to. If not de ned, the
port will be chosen randomly.
devservices.shared
Indicates if the Redis broker managed by Quarkus Dev Services is
shared. When shared, Quarkus looks for running containers using
label-based service discovery. (default: true)
devservices.service-name
The value of the quarkus-dev-service-redis label attached to the
started container. (default: redis)
Multiple Redis Clients
quarkus.redis.hosts = localhost:6379
quarkus.redis.second.hosts = localhost:6379
@Inject
RedisClient defaultRedisClient;
@Inject
@RedisClientName("second")
RedisClient redisClient2;
List of Redis parameters.
quarkus.redis as pre x is skipped in the next table.
health.enabled
Health check is published in case the smallrye-health extension
is present. (default: true)
password
The Redis password.
hosts
The Redis hosts. (default: localhost:6379)
database
The Redis database.
timeout
The maximum delay to wait before a blocking command to redis
server times out. (default: 10s)
ssl
Enables or disables the SSL on connect.
clinet-type
The Redis client type. Possible values: standalone, cluster,
sentinel (default: standalone)
Flyway
Quarkus integrates with Flyway to help you on database schema
migrations.
./mvnw quarkus:add-extension
-Dextensions="quarkus-flyway"
Then place migration les to the migrations folder
(classpath:db/migration).
You can inject org.flywaydb.core.Flyway to programmatically
execute the migration.
@Inject
Flyway flyway;
flyway.migrate();
Or can be automatically executed by setting migrate-at-start
property to true
quarkus.flyway.migrate-at-start=true
List of Flyway parameters.
quarkus.flyway as pre x is skipped in the next table.
clean-at-start
Execute Flyway clean command (default: false)
migrate-at-start
Flyway migration automatically (default: false)
locations
CSV locations to scan recursively for migrations. Supported
pre xes classpath and filesystem (default:
classpath:db/migration).
connect-retries
The maximum number of retries when attempting to connect
(default: 0)
schemas
CSV case-sensitive list of schemas managed (default: none)
table
The name of Flyway’s schema history table (default:
flyway_schema_history)
out-of-order
Allows migrations to be run "out of order".
ignore-missing-migrations
Ignore missing migrations when reading the history table.
sql-migration-prefix
Pre x for versioned SQL migrations (default: V)
repeatable-sql-migration-prefix:: Pre x for repeatable SQL
migrations (default: R)
baseline-on-migrate
Only migrations above baseline-version will then be applied
baseline-version
Version to tag an existing schema with when executing baseline
(default: 1)
baseline-description
Description to tag an existing schema with when executing
baseline (default: Flyway Baseline)
validate-on-migrate
Validate the applied migrations against the available ones
(default: true)
placeholder-prefix
Pre x of every placeholder (default: ${)
placeholder-suffix
Su x of every placeholder (default: })
callbacks
Comma-separated list of fully quali ed class names of Callback
implementations.
ignore-future-migrations
Ignore future migrations when reading the history table.
Multiple Datasources
To use multiple datasource in Flyway you just need to add the
datasource name just after the flyway property:
quarkus.datasource.users.jdbc.url=jdbc:h2:tcp://localhost/m
em:users
quarkus.datasource.inventory.jdbc.url=jdbc:h2:tcp://localho
st/mem:inventory
# ...
quarkus.flyway.users.schemas=USERS_TEST_SCHEMA
quarkus.flyway.inventory.schemas=INVENTORY_TEST_SCHEMA
# ...
Liquibase
Quarkus integrates with Liquibase to help you on database schema
migrations.
./mvnw quarkus:add-extension
-Dextensions="quarkus-liquibase"
Then place changelog les to the (src/main/resources/db) folder.
You can inject org.quarkus.liquibase.LiquibaseFactory to
programmatically execute the migration.
@Inject
LiquibaseFactory liquibaseFactory;
try (Liquibase liquibase = liquibaseFactory.createLiquibase
()) {
...
}
Or can be automatically executed by setting migrate-at-start
property to true.
quarkus.liquibase.migrate-at-start=true
List of Liquibase parameters.
quarkus.liquibase as pre x is skipped in the next table.
change-log
The change log le. XML, YAML , JSON, SQL formats supported.
(default: db/changeLog.xml)
change-log-parameters."<parameter-name>"
Liquibase changelog parameters.
migrate-at-start
The migrate at start ag. (default: false)
validate-on-migrate
The validate on update ag. (default: false)
clean-at-start
The clean at start ag. (default: false)
contexts
The list of contexts.
labels
The list of labels.
database-change-log-table-name
The database change log lock table name. (default:
DATABASECHANGELOG)
database-change-log-lock-table-name
The database change log lock table name. (default:
DATABASECHANGELOGLOCK)
default-catalog-name
The default catalog name.
default-schema-name
The default schema name.
liquibase-catalog-name
The liquibase tables catalog name.
liquibase-schema-name
The liquibase tables schema name.
liquibase-tablespace-name
The liquibase tables tablespace name.
Multiple Datasources
To use multiple datasource in Liquibase you just need to add the
datasource name just after the liquibase property:
quarkus.datasource.users.jdbc.url=jdbc:h2:tcp://localhost/m
em:users
quarkus.datasource.inventory.jdbc.url=jdbc:h2:tcp://localho
st/mem:inventory
# ...
quarkus.liquibase.users.schemas=USERS_TEST_SCHEMA
quarkus.liquibase.inventory.schemas=INVENTORY_TEST_SCHEMA
# ...
Liquibase MongoDB
./mvnw quarkus:add-extension
-Dextensions="liquibase-mongodb"
Most of the con guration properties are valid but changing pre x
to: quarkus.liquibase-mongodb
Hibernate Search
Quarkus integrates with Elasticsearch to provide a full-featured full-
text search using Hibernate Search API.
./mvnw quarkus:add-extension
-Dextensions="quarkus-hibernate-search-elasticsearch"
You need to annotate your model with Hibernate Search API to
index it:
@Entity
@Indexed
public class Author extends PanacheEntity {
@FullTextField(analyzer = "english")
public String bio;
@FullTextField(analyzer = "name")
@KeywordField(name = "firstName_sort",
sortable = Sortable.YES,
normalizer = "sort")
public String firstName;
@OneToMany
@IndexedEmbedded
public List<Book> books;
}
It is not mandatory to use Panache.
You need to de ne the analyzers and normalizers de ned in
annotations. You only need to implement
ElasticsearchAnalysisConfigurer interface and con gure it.
public class MyQuarkusAnalysisConfigurer
implements ElasticsearchAnalysisConfigurer {
@Override
public void configure(
ElasticsearchAnalysisDefinitionContainerContext ct
x)
{
ctx.analyzer("english").custom()
.withTokenizer("standard")
.withTokenFilters("asciifolding",
"lowercase", "porter_stem");
ctx.normalizer("sort").custom()
.withTokenFilters("asciifolding", "lowercase");
}
}
Use Hibernate Search in REST service:
public class LibraryResource {
@Inject
EntityManager em;
@Transactional
public List<Author> searchAuthors(
@QueryParam("pattern") String pattern) {
return Search.getSearchSession(em)
.search(Author.class)
.predicate(f ->
pattern == null || pattern.isEmpty() ?
f.matchAll() :
f.simpleQueryString()
.onFields("firstName",
"lastName", "books.title")
.matching(pattern)
)
.sort(f -> f.byField("lastName_sort")
.then().byField("firstName_sort"))
.fetchHits();
}
When not using Hibernate ORM, index data using
Search.getSearchSession(em).createIndexer()
.startAndWait() at startup time.
Con gure the extension in application.properties:
quarkus.hibernate-search.elasticsearch.version=7
quarkus.hibernate-search.elasticsearch.
analysis-configurer=MyQuarkusAnalysisConfigurer
quarkus.hibernate-search.elasticsearch.
automatic-indexing.synchronization-strategy=searchable
quarkus.hibernate-search.elasticsearch.
index-defaults.lifecycle.strategy=drop-and-create
quarkus.hibernate-search.elasticsearch.
index-defaults.lifecycle.required-status=yellow
List of Hibernate-Elasticsearch properties pre xed with
quarkus.hibernate-search.elasticsearch:
backends
Map of con guration of additional backends.
version
Version of Elasticsearch
analysis-configurer
Class or name of the neab used to con gure.
hosts
List of Elasticsearch servers hosts.
enabled
Whether Hibernate Search is enabled. (default: true)
username
Username for auth.
password
Password for auth.
connection-timeout
Duration of connection timeout.
max-connections
Max number of connections to servers.
max-connections-per-route
Max number of connections to server.
indexes
Per-index speci c con guration.
discovery.enabled
Enables automatic discovery.
discovery.refresh-interval
Refresh interval of node list.
discovery.default-scheme
Scheme to be used for the new nodes.
automatic-indexing.synchronization-strategy
Status for which you wait before considering the operation
completed (queued,committed or searchable).
automatic-indexing.enable-dirty-check
When enabled, re-indexing of is skipped if the changes are on
properties that are not used when indexing.
index-defaults.lifecycle.strategy
Index lifecycle (none, validate, update, create, drop-and-create,
drop-abd-create-drop)
index-defaults lifecycle required-status
Minimal cluster status (green, yellow, red)
index-defaults.lifecycle.required-status-wait-timeout
Waiting time before failing the bootstrap.
index-defaults.refresh-after-write
Set if index should be refreshed after writes.
Possible annotations:
@Indexed
Register entity as full text index
@FullTextField
Full text search. Need to set an analyzer to split tokens.
@KeywordField
The string is kept as one single token but can be normalized.
IndexedEmbedded
Include the Book elds into the Author index.
@ContainerExtraction
Sets how to extract a value from container, e.g from a Map.
@DocumentId
Map an unusual entity identi er to a document identi er.
@GenericField
Full text index for any supported type.
@IdentifierBridgeRef
Reference to the identi er bridge to use for a @DocumentId.
@IndexingDependency
How a dependency of the indexing process to a property should
affect automatic reindexing.
@ObjectPath
@ScaledNumberField
For java.math.BigDecimal or java.math.BigInteger that you need
higher precision.
If you are using ElasticSearch in AWS you might need some extra
con g provided by an special extension
https://quarkiverse.github.io/quarkiverse-docs/quarkus-hibernate-
search-extras/dev/index.html
Amazon DynamoDB
Quarkus integrates with https://aws.amazon.com/dynamodb/:
./mvnw quarkus:add-extension
-Dextensions="quarkus-amazon-dynamodb"
@Inject
DynamoDbClient dynamoDB;
To use asycnhronous client with Mutiny:
./mvnw quarkus:add-extension
-Dextensions="quarkus-amazon-dynamodb, resteasy-mutiny"
@Inject
DynamoDbAsyncClient dynamoDB;
Uni.createFrom().completionStage(() -> dynamoDB.scan(scanRe
quest()))....
To use it as a local DynamoDB instance:
quarkus.dynamodb.region=
eu-central-1
quarkus.dynamodb.endpoint-override=
http://localhost:8000
quarkus.dynamodb.credentials.type=STATIC
quarkus.dynamodb.credentials.static-provider
.access-key-id=test-key
quarkus.dynamodb.credentials.static-provider
.secret-access-key=test-secret
If you want to work with an AWS account, you’d need to set it with:
quarkus.dynamodb.region=<YOUR_REGION>
quarkus.dynamodb.credentials.type=DEFAULT
DEFAULT credentials provider chain:
System properties aws.accessKeyId, aws.secretKey
Env. Varables AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY
Credentials pro le ~/.aws/credentials
Credentials through the Amazon EC2 container service if the
AWS_CONTAINER_CREDENTIALS_RELATIVE_URI set
Credentials through Amazon EC2 metadata service.
Con guration parameters pre xed with quarkus.dynamodb:
Parameter Default Description
enable-endpoint-
discovery
false
Endpoint discovery
for a service API that
supports endpoint
discovery.
endpoint-override Con gure the
endpoint with which
the SDK should
communicate.
api-call-timeout
Time to complete an
execution.
interceptors
List of class
interceptors.
Con guration parameters pre xed with quarkus.dynamodb.aws:
Parameter Default Description
region
Region that hosts
DynamoDB.
credentials.type DEFAULT
Credentials that
should be used
DEFAULT, STATIC,
SYSTEM_PROPERTY,
ENV_VARIABLE,
PROFILE, CONTAINER,
INSTANCE_PROFILE,
PROCESS, ANONYMOUS
Credentials speci c parameters pre xed with
quarkus.dynamodb.aws.credentials:
Parameter Default Description
DEFAULT
default-
provider.async-
credential-update-
enabled
false
Should fetch
credentials async.
default-
provider.reuse-last-
provider-enabled
true
Should reuse the last
successful
credentials.
STATIC
static-
provider.access-key-
id
AWS access key id.
static-
provider.secret-
access-key
AWS secret access
key.
Parameter Default Description
PROFILE
profile-
provider.profile-name
default
The name of the
pro le to use.
PROCESS
process-
provider.command
Command to execute
to retrieve
credentials.
process-
provider.process-
output-limit
1024
Max bytes to retrieve
from process.
process-
provider.credential-
refresh-threshold
PT15S
The amount of time
between credentials
expire and
credentials refreshed.
process-
provider.async-
credential-update-
enabled
false
Should fetch
credentials async.
In case of synchronous client, the next parameters can be
con gured pre xed by quarkus.dynamodb.sync-client:
Parameter Default Description
connection-
acquisition-timeout
10S
Connection
acquisation timeout.
connection-max-idle-
time
60S
Max time to
connection to be
opened.
connection-timeout Connection timeout.
connection-time-to-
live
0
Max time connection
to be open.
socket-timeout 30S Time to wait for data.
max-connections 50 Max connections.
expect-continue-
enabled
true
Client send an HTTP
expect-continue
handsake.
Parameter Default Description
use-idle-connection-
reaper
true
Connections in pool
should be closed
asynchronously.
proxy.endpoint
Endpoint of the proxy
server.
proxy.enabled false Enables HTTP proxy.
proxy.username Proxy username.
proxy.password Proxy password.
proxy.ntlm-domain
For NTLM, domain
name.
proxy.ntlm-
workstation
For NTLM,
workstation name.
proxy.preemptive-
basic-authentication-
enabled
Authenticate pre-
emptively.
proxy.non-proxy-
hosts
List of non proxy
hosts.
tls-managers-
provider.type
system-property
TLS manager: none,
system-property,
file-store
tls-managers-
provider.file-
store.path
Path to key store.
tls-managers-
provider.file-
store.type
Key store type.
tls-managers-
provider.file-
store.password
Key store password.
In case of asynchronous client, the next parameters can be
con gured pre xed by quarkus.dynamodb.async-client:
Parameter Default Description
connection-
acquisition-timeout
10S
Connection
acquisation timeout.
Parameter Default Description
connection-max-idle-
time
60S
Max time to
connection to be
opened.
connection-timeout Connection timeout.
connection-time-to-
live
0
Max time connection
to be open.
max-concurrency 50
Max number of
concurrent
connections.
use-idle-connection-
reaper
true
Connections in pool
should be closed
asynchronously.
read-timeout 30S Read timeout.
write-timeout 30S Write timeout.
proxy.endpoint
Endpoint of the proxy
server.
proxy.enabled false Enables HTTP proxy.
proxy.non-proxy-
hosts
List of non proxy
hosts.
tls-managers-
provider.type
system-property
TLS manager: none,
system-property,
file-store
tls-managers-
provider.file-
store.path
Path to key store.
tls-managers-
provider.file-
store.type
Key store type.
tls-managers-
provider.file-
store.password
Key store password.
ssl-provider
SSL Provider (jdk,
openssl, openssl-
refcnt).
Parameter Default Description
protocol HTTP_1_1
Sets the HTTP
protocol.
max-http2-streams
Max number of
concurrent streams.
event-loop.override false
Enable custom event
loop conf.
event-loop.number-of-
threads
Number of threads to
use in event loop.
event-loop.thread-
name-prefix
aws-java-sdk-
NettyEventLoop
Pre x of thread
names.
Amazon S3
./mvnw quarkus:add-extension
-Dextensions="quarkus-amazon-s3"
@Inject
S3Client s3Client;
You need to set a HTTP client either URL Connection:
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>url-connection-client</artifactId>
</dependency>
or Apache HTTP:
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>apache-client</artifactId>
</dependency>
quarkus.s3.sync-client.type=apache
And con gure it:
quarkus.s3.endpoint-override=http://localhost:8008
quarkus.s3.interceptors=io.quarkus.it.amazon.s3.S3ModifyRes
ponse
quarkus.s3.aws.region=us-east-1
quarkus.s3.aws.credentials.type=static
quarkus.s3.aws.credentials.static-provider.access-key-id=te
st-key
quarkus.s3.aws.credentials.static-provider.secret-access-ke
y=test-secret
You can inject asynchronous client too:
@Inject
S3AsyncClient s3AsyncClient;
And you need to add the asynchronous Netty client:
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>netty-nio-client</artifactId>
</dependency>
Con guration properties are the same as Amazon DynamoDB but
changing the pre x from dynamodb to s3.
Neo4j
Quarkus integrates with Neo4j:
./mvnw quarkus:add-extension
-Dextensions="quarkus-neo4j"
@Inject
org.neo4j.driver.Driver driver;
Con guration properties:
quarkus.neo4j as pre x is skipped in the next table.
Pre x is quarkus.neo4j.
uri
URI of Neo4j. (default: localhost:7687)
authentication.username
Username. (default: neo4j)
authentication.password
Password. (default: neo4j)
authentication.disabled
Disable authentication. (default: false)
Enable metrics. (default: false)
pool.log-leaked-sessions
Enable leaked sessions logging. (default:`false`)
pool.max-connection-pool-size
Max amount of connections. (default: 100)
pool.max-connection-lifetime
Pooled connections older will be closed and removed from the
pool. (default: 1H)
pool.connection-acquisition-timeout
Timout for connection adquisation. (default: 1M)
pool.idle-time-before-connection-test
Pooled connections idled in the pool for longer than this timeout
will be tested before they are used. (default: -1)
As Neo4j uses SSL communication by default, to create a native
executable you need to compile with next options GraalVM options:
-H:EnableURLProtocols=http,https --enable-all-security-services -
H:+JNI
And Quarkus Maven Plugin with next con guration:
<artifactId>quarkus-maven-plugin</artifactId>
<executions>
<execution>
<id>native-image</id>
<goals>
<goal>native-image</goal>
</goals>
<configuration>
<enableHttpUrlHandler>true
</enableHttpUrlHandler>
<enableHttpsUrlHandler>true
</enableHttpsUrlHandler>
<enableAllSecurityServices>true
</enableAllSecurityServices>
<enableJni>true</enableJni>
</configuration>
</execution>
</executions>
Alternatively, and as a not recommended way in production, you
can disable SSL and Quarkus will disable Bolt SSL as well.
quarkus.ssl.native=false.
If you are using Neo4j 4.0, you can use fully reactive. Add the next
extension: quarkus-resteasy-mutiny.
@GET
public Publisher<String> get() {
return Multi.createFrom().resource(driver::rxSession,
session -> session.readTransaction(tx -> {
RxResult result = tx.run("MATCH (f:Fruit) RETUR
N f.name as name");
return Multi.createFrom().publisher(result.reco
rds())
.map(record -> record.get("name").asStr
ing());
})
).withFinalizer(session -> {
return Uni.createFrom().publisher(session.close());
});
}
DevServices
When testing or running in dev mode Quarkus can even provide you
with a zero con g Neo4j out of the box.
Possible con guration values are shown at Neo4J
MongoDB Client
Quarkus integrates with MongoDB:
./mvnw quarkus:add-extension
-Dextensions="quarkus-mongodb-client"
@Inject
com.mongodb.client.MongoClient client;
@Inject
io.quarkus.mongodb.reactive.ReactiveMongoClient client;
INFO: Reactive client uses exposes Mutiny API.
quarkus.mongodb.connection-string=mongodb://localhost:27018
quarkus.mongodb.write-concern.journal=false
Testing
To start an embedded MongoDB database for your unit tests,
Quarkus provides two QuarkusTestResourceLifecycleManager.
Add io.quarkus:quarkus-test-mongodb dependency.
// Single MongoDB instance
@QuarkusTestResource(io.quarkus.test.mongodb.MongoTestResou
rce.class)
// ReplicaSet with two instances
@QuarkusTestResource(io.quarkus.test.mongodb.MongoReplicaSe
tTestResource.class)
Multi MongoDB support
You can con gure multiple MongoDB clients using same approach
as with DataSource. The syntax is quarkus.mongodb.<optional name>.
<property>:
quarkus.mongodb.users.connection-string = mongodb://mongo2:
27017/userdb
quarkus.mongodb.inventory.connection-string = mongodb://mon
go3:27017/invdb
Inject the instance using
@io.quarkus.mongodb.runtime.MongoClientName annotation:
@Inject
@MongoClientName("users")
MongoClient mongoClient1;
DevServices
When testing or running in dev mode Quarkus can even provide you
with a zero con g MongoDB database out of the box.
%prod.quarkus.mongodb.connection-string=mongodb://localhos
t:27018
Possible con guration values pre xed with quarkus.datasource:
devservices.enabled
If devservices is enabled or not. (default: true)
devservices.image-name
The container image name to use instead of the default one.
devservices.port
Optional xed port the dev service will listen to. If not de ned, the
port will be chosen randomly.
devservices.properties
Generic properties that are added to the database connection
URL.
quarkus.mongodb as pre x is skipped in the following table.
Parameter Type Description
connection-string String
MongoDB connection
URI.
hosts List<String>
Addresses passed as
host:port.
application-name String Application name.
max-pool-size Int
Maximum number of
connections.
min-pool-size Int
Minimum number of
connections.
max-connection-idle-
time
Duration
Idle time of a pooled
connection.
max-connection-life-
time
Duration
Life time of pooled
connection.
wait-queue-timeout Duration
Maximum wait time
for new connection.
maintenance-
frequency
Duration
Time period between
runs of maintenance
job.
maintenance-initial-
delay
Duration
Time to wait before
running the rst
maintenance job.
wait-queue-multiple Int
Multiplied with max-
pool-size gives max
numer of threads
waiting.
connection-timeout Duration
socket-timeout Duration
tls-insecure boolean [false] Insecure TLS.
tls boolean [false] Enable TLS
Parameter Type Description
replica-set-name String
Implies hosts given
are a seed list.
server-selection-
timeout
Duration
Time to wait for
server selection.
local-threshold Duration
Minimum ping time
to make a server
eligible.
heartbeat-frequency Duration
Frequency to
determine the state
of servers.
read-preference
primary,
primaryPreferred,
secondary,
secondaryPreferred,
nearest
Read preferences.
max-wait-queue-size Int
Max number of
concurrent
operations allowed to
wait.
write-concern.safe boolean [true]
Ensures are writes
are ack.
write-
concern.journal
boolean [true]
Journal writing
aspect.
write-concern.w String
Value to all write
commands.
write-concern.retry-
writes
boolean [false]
Retry writes if
network fails.
write-concern.w-
timeout
Duration
Timeout to all write
commands.
credentials.username String Username.
credentials.password String Password.
credentials.auth-
mechanism
MONGO-CR, GSSAPI,
PLAIN, MONGODB-X509
Parameter Type Description
credentials.auth-
source
String
Source of the
authentication
credentials.
credentials.auth-
mechanism-properties
Map<String, String>
Authentication
mechanism
properties.
read-concern String
Con gures the read
concern. Possible
values: local,
majority,
linearizable,
snapshot, available
MongoDB Panache
You can also use the Panache framework to write persistence part
when using MongoDB.
./mvnw quarkus:add-extension
-Dextensions="mongodb-panache"
MongoDB con guration comes from MongoDB Client section.
@MongoEntity(collection="ThePerson")
public class Person extends PanacheMongoEntity {
public String name;
@BsonProperty("birth")
public LocalDate birthDate;
public Status status;
}
Possible annotations in elds: @BsonId (for custom ID),
@BsonProperty and @BsonIgnore.
@MongoEntity is optional.
Multi-tenancy with MongoDB Panache
@MongoEntity(collection = "TheBook", clientName = "client2"
, database = "database2")
Methods provided are similar of the ones shown in Persistence
section.
person.persist();
person.update();
person.delete();
List<Person> allPersons = Person.listAll();
person = Person.findById(personId);
List<Person> livingPersons = Person.list("status", Status.A
live);
List<Person> persons = Person.list(Sort.by("name").and("bir
th"));
long updated = Person.update("name", "Mortal").where("statu
s", Status.Alive);
long countAll = Person.count();
Person.deleteById(id);
Person.delete("status", Status.Alive);
All list methods have equivalent stream versions.
Pagination
You can also use pagination:
PanacheQuery<Person> livingPersons =
Person.find("status", Status.Alive);
livingPersons.page(Page.ofSize(25));
// get the first page
List<Person> firstPage = livingPersons.list();
// get the second page
List<Person> secondPage = livingPersons.nextPage().list();
Range
PanacheQuery<Person> livingPersons = Person
.find("status", Status.Alive);
List<Person> secondRange = livingPersons.range(25, 49).list
();
You cannot mix pagination and range.
Queries
Native MongoDB queries are supported (if they start with { or
org.bson.Document instance) as well as Panache Queries. Panache
Queries equivalence in MongoDB:
firstname = ?1 and status = ?2 → {'firstname': ?1, 'status': ?
2}
amount > ?1 and firstname != ?2 → {'amount': {'$gt': ?1},
'firstname': {'$ne': ?2}}
lastname like ?1 → {'lastname': {'$regex': ?1}}
lastname is not null → {'lastname':{'$exists': true}}
PanacheQL refers to the Object parameter name but native
queries refer to MongoDB eld names.
Projection
Projection can be done for both PanacheQL and native queries.
import io.quarkus.mongodb.panache.ProjectionFor;
@ProjectionFor(Person.class) (1)
public class PersonName {
public String name;
}
PanacheQuery<PersonName> shortQuery = Person.find("status "
, Status.Alive).project(PersonName.class);
1 Entity class.
Transsactions
To use them with MongoDB with Panache you need to annotate the
method that starts the transaction with the @Transactional
annotation.
Testing
To mock using active record pattern:
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-panache-mock</artifactId>
<scope>test</scope>
</dependency>
@Test
public void testPanacheMocking() {
PanacheMock.mock(Person.class);
Mockito.when(Person.count()).thenReturn(23l);
Assertions.assertEquals(23, Person.count());
PanacheMock.verify(Person.class, Mockito.times(1)).coun
t();
}
DAO pattern
@ApplicationScoped
public class PersonRepository
implements PanacheMongoRepository<Person> {
}
Jandex
If entities are de ned in external JAR, you need to enable in these
projects the Jandex plugin in project.
<plugin>
<groupId>org.jboss.jandex</groupId>
<artifactId>jandex-maven-plugin</artifactId>
<version>1.0.3</version>
<executions>
<execution>
<id>make-index</id>
<goals>
<goal>jandex</goal>
</goals>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>org.jboss</groupId>
<artifactId>jandex</artifactId>
<version>2.1.1.Final</version>
</dependency>
</dependencies>
</plugin>
Panache includes an annotation processor that enhance your
entities. If you disable annotation processors you might need to
create a marker le on Panache archives at META-INF/panache-
archive.marker manually.
Reactive Panache
MongoDB with Panache allows using reactive implementation too
by using ReactivePanacheMongoEntity or
ReactivePanacheMongoEntityBase or ReactivePanacheMongoRepository
or ReactivePanacheMongoRepositoryBase depending on your style.
public class ReactivePerson extends ReactivePanacheMongoEnt
ity {
public String name;
}
CompletionStage<Void> cs1 = person.persist();
CompletionStage<List<ReactivePerson>> allPersons = Reactive
Person.listAll();
Publisher<ReactivePerson> allPersons = ReactivePerson.strea
mAll();
Uni<List<PersonName>> persons = ReactivePersonEntity.find(
"lastname", name).project(PersonName.class).list();
MongoDB REST Data Panache
MongoDB REST Data with Panache extension can generate the
basic CRUD endpoints for your entities and repositories.
./mvnw quarkus:add-extension
-Dextensions="mongodb-rest-data-panache"
You also need to add the JDBC driver extension and a JSON
Marshaller (ie resteasy-jackson).
Then you can de ne interfaces for de ning endpoints:
In case of Active Record pattern:
public interface DeveloperResource extends PanacheMongoEnti
tyResource<Developer, Long> {
}
In case of Repository:
public interface DeveloperResource extends PanacheMongoRepo
sitoryResource<DeveloperRepository, Developer, Long> {
}
Cassandra
Quarkus integrates with Cassandra and DataStax Object Mapper.
<dependency>
<groupId>com.datastax.oss.quarkus</groupId>
<artifactId>cassandra-quarkus-client</artifactId>
</dependency>
Enities and DAOs are generated as you have been doing with
DataStax Object Mapper.
You need to create a DaoProducer:
@Inject
public FruitDaoProducer(QuarkusCqlSession session) {
FruitMapper mapper = new FruitMapperBuilder(session).buil
d();
fruitDao = mapper.fruitDao();
}
@Produces
@ApplicationScoped
FruitDao produceFruitDao() {
return fruitDao;
}
Cassandra con guration:
quarkus.cassandra.contact-points=127.0.0.1:9042
quarkus.cassandra.local-datacenter=datacenter1
quarkus.cassandra.keyspace=k1
quarkus.cassandra.auth.username=john
quarkus.cassandra.auth.password=s3cr3t
You can con gure other Cassandra Java driver settings using
application.conf or application.json les. They need to be located
in the classpath of your application. Driver settings reference.
If MicroPro le Metrics extension is registered, the Cassandra
extension can provide (if enabled) metrics about the session:
quarkus.cassandra.metrics.enabled=true
quarkus.cassandra.metrics.session-enabled=connected-nodes,b
ytes-sent
quarkus.cassandra.metrics.node-enabled=pool.open-connection
s
Reactive
You can also use Mutiny to de ne a reactive DAO:
@Dao
public interface FruitDaoReactive {
@Update
Uni<Void> update(Fruit fruit);
@Select
MutinyMappedReactiveResultSet<Fruit> findById(String stor
eId);
}
@Mapper
public interface FruitMapper {
@DaoFactory
FruitDaoReactive fruitDaoReactive();
}
Reactive Programming
Quarkus implements MicroPro le Reactive spec and uses RXJava2
to provide reactive programming model.
./mvnw quarkus:add-extension
-Dextensions="quarkus-smallrye-reactive-streams-operator
s"
Asynchronous HTTP endpoint is implemented by returning Java
CompletionStage. You can create this class either manually or using
MicroPro le Reactive Streams spec:
@GET
@Path("/reactive")
@Produces(MediaType.TEXT_PLAIN)
public CompletionStage<String> getHello() {
return ReactiveStreams.of("h", "e", "l", "l", "o")
.map(String::toUpperCase)
.toList()
.run()
.thenApply(list -> list.toString());
}
Creating streams is also easy, you just need to return Publisher
object.
@GET
@Path("/stream")
@Produces(MediaType.SERVER_SENT_EVENTS)
public Publisher<String> publishers() {
return Flowable
.interval(500, TimeUnit.MILLISECONDS)
.map(s -> atomicInteger.getAndIncrement())
.map(i -> Integer.toString(i));
}
Mutiny and JAX-RS
Apart from the CompletionStage support, there is also support for
Mutiny.
./mvnw quarkus:add-extension
-Dextensions="quarkus-resteasy-mutiny"
@GET
@Produces(MediaType.TEXT_PLAIN)
public Uni<String> hello() {
return Uni.createFrom().item(() -> "hello");
}
@GET
@Produces(MediaType.TEXT_PLAIN)
public Multi<String> multi() {
return Multi.createFrom().items("hello", "world");
}
Mutiny
Quarkus integrates with Mutiny as reactive programming library:
./mvnw quarkus:add-extension
-Dextensions="mutiny"
@ApplicationScoped
public static class ReactiveHello {
public Uni<String> greeting() {
return Uni.createFrom().item(() -> "hello")
.emitOn(Infrastructure.getDefaultExecutor
());
}
public Multi<String> stream() {
return Multi.createFrom().items("hello", "world")
.emitOn(Infrastructure.getDefaultExecutor
());
}
}
Converting from/to RxJava2 or Reactor APIs:
RxJava 2
<dependency>
<groupId>io.smallrye.reactive</groupId>
<artifactId>mutiny-rxjava</artifactId>
</dependency>
From RxJava2:
Uni<Void> uniFromCompletable = Uni.createFrom()
.converter(UniRxConvert
ers.fromCompletable(), completable);
Uni<String> uniFromSingle = Uni.createFrom()
.converter(UniRxConverters.
fromSingle(), single);
Uni<String> uniFromObservable = Uni.createFrom()
.converter(UniRxConverters.
fromObservable(), observable);
Uni<String> uniFromFlowable = Uni.createFrom()
.converter(UniRxConverters.
fromFlowable(), flowable);
...
Multi<Void> multiFromCompletable = Multi.createFrom()
.converter(MultiRxC
onverters.fromCompletable(), completable);
Multi<String> multiFromObservable = Multi.createFrom()
.converter(MultiRxC
onverters.fromObservable(), observable);
Multi<String> multiFromFlowable = Multi.createFrom()
.converter(MultiRxC
onverters.fromFlowable(), flowable);
...
To RxJava2:
Completable completable = uni.convert().with(UniRxConverter
s.toCompletable());
Single<Optional<String>> single = uni.convert().with(UniRxC
onverters.toSingle());
Observable<String> observable = uni.convert().with(UniRxCon
verters.toObservable());
Flowable<String> flowable = uni.convert().with(UniRxConvert
ers.toFlowable());
...
Completable completable = multi.convert().with(MultiRxConve
rters.toCompletable());
Single<Optional<String>> single = multi.convert().with(Mult
iRxConverters.toSingle());
Observable<String> observable = multi.convert().with(MultiR
xConverters.toObservable());
Flowable<String> flowable = multi.convert().with(MultiRxCon
verters.toFlowable());
...
Reactor API
<dependency>
<groupId>io.smallrye.reactive</groupId>
<artifactId>mutiny-reactor</artifactId>
</dependency>
From Reactor:
Uni<String> uniFromMono = Uni.createFrom().converter(UniRea
ctorConverters.fromMono(), mono);
Uni<String> uniFromFlux = Uni.createFrom().converter(UniRea
ctorConverters.fromFlux(), flux);
Multi<String> multiFromMono = Multi.createFrom().converter
(MultiReactorConverters.fromMono(), mono);
Multi<String> multiFromFlux = Multi.createFrom().converter
(MultiReactorConverters.fromFlux(), flux);
To Reactor:
Mono<String> mono = uni.convert().with(UniReactorConverter
s.toMono());
Flux<String> flux = uni.convert().with(UniReactorConverter
s.toFlux());
Mono<String> mono2 = multi.convert().with(MultiReactorConve
rters.toMono());
Flux<String> flux2 = multi.convert().with(MultiReactorConve
rters.toFlux());
CompletionStages or Publisher
CompletableFuture<String> future = Uni
.createFrom().completionStage(CompletableFuture.sup
plyAsync(() -> "hello"));
CompletationStage<String> cs = Uni
.createFrom().subscribeAsCompletionStage();
Multi implements Publisher.
RESTEasy Reactive
RESTEasy Reactive is a new implementation of JAX-RS but fully
reactive.
mvn quarkus:add-extension
-Dextensions="quarkus-resteasy-reactive"
package org.acme.rest;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
@Path("rest")
public class Endpoint {
@Path("hello")
@GET
public String hello(){
// executed in event-loop
return "Hello, World!";
}
@GET
public Uni<Book> culinaryGuide(){
// executed in event-loop but not blocking
return Book.findByIsbn("978-2081229297");
}
@io.smallrye.common.annotation.Blocking
@GET
public String blockingHello() throws InterruptedExcepti
on {
// executed in worker-thread
return "Yaaaawwwwnnnnnn…";
}
}
Reactive Messaging
Quarkus relies on MicroPro le Reactive Messaging spec to
implement reactive messaging streams.
mvn quarkus:add-extension
-Dextensions="
io.quarkus:quarkus-smallrye-reactive-messaging"
You can just start using in-memory streams by using @Incoming to
produce data and @Outgoing to consume data.
Produce every 5 seconds one piece of data.
@ApplicationScoped
public class ProducerData {
@Outgoing("my-in-memory")
public Flowable<Integer> generate() {
return Flowable.interval(5, TimeUnit.SECONDS)
.map(tick -> random.nextInt(100));
}
}
or in Mutiny:
@ApplicationScoped
public class ProducerData {
@Outgoing("my-in-memory")
public Multi<Integer> generate() {
return Multi.createFrom().ticks().every(Duration.of
Seconds(5))
.onItem().apply(n -> random.nextInt(100));
}
}
If you want to dispatch to all subscribers you can annotate the
method with @Broadcast.
Consumes generated data from my-in-memory stream.
@ApplicationScoped
public class ConsumerData {
@Incoming("my-in-memory")
public void randomNumber(int randomNumber) {
System.out.println("Received " + randomNumber);
}
}
You can also inject an stream as a eld:
@Inject
@Stream("my-in-memory") Publisher<Integer> randomRumbers;
@Inject @Stream("generated-price")
Emitter<String> emitter;
Patterns
REST API → Message
@Inject @Stream(“in”)
Emitter<String> emitter;
emitter.send(message);
Message → Message
@Incoming(“in”)
@Outgoing(“out”)
public String process(String in) {
}
Message → SSE
@Inject @Stream(“out”)
Publisher<String> result;
@GET
@Produces(SERVER_SENT_EVENTS)
public Publisher<String> stream() {
return result;
}
Message → Business Logic
@ApplicationScoped
public class ReceiverMessages {
@Incoming("prices")
public void print(String price) {
}
}
To indicate that the method should be executed on a worker pool
you can use @Blocking:
@Outgoing("Y")
@Incoming("X")
@Blocking
To customize:
@Blocking(value="my-custom-pool", ordered = false)
smallrye.messaging.worker.my-custom-pool.max-concurrency=3
Possible implementations are:
In-Memory
If the stream is not con gured then it is assumed to be an in-
memory stream, if not then stream type is de ned by connector
eld.
Kafka
To integrate with Kafka you need to add next extensions:
mvn quarkus:add-extension
-Dextensions="
io.quarkus:quarkus-smallrye-reactive-messaging-kafka"
Then @Outgoing, @Incoming or @Stream can be used.
Kafka con guration schema: mp.messaging.[outgoing|incoming].
{stream-name}.<property>=<value>.
The connector type is smallrye-kafka.
mp.messaging.outgoing.generated-price.connector=
smallrye-kafka
mp.messaging.outgoing.generated-price.topic=
prices
mp.messaging.outgoing.generated-price.bootstrap.servers=
localhost:9092
mp.messaging.outgoing.generated-price.value.serializer=
org.apache.kafka.common.serialization.IntegerSerializer
mp.messaging.incoming.prices.connector=
smallrye-kafka
mp.messaging.incoming.prices.value.deserializer=
org.apache.kafka.common.serialization.IntegerDeserializ
er
A complete list of supported properties are in Kafka site. For the
producer and for consumer
JSON-B Serializer/Deserializer
You can use JSON-B to serialize/deserialize objects.
./mvnw quarkus:add-extension
-Dextensions="quarkus-kafka-client"
To serialize you can use
io.quarkus.kafka.client.serialization.JsonbSerializer.
To deserialize you need to extend
io.quarkus.kafka.client.serialization.JsonbDeserializer and
provide a type.
public class BeerDeserializer
extends JsonbDeserializer<Beer> {
public BeerDeserializer() {
super(Beer.class);
}
}
DevServices
When testing or running in dev mode Quarkus can even provide you
with a zero con g Kafka out of the box.
Possible con guration values pre xed with quarkus.kafka:
devservices.enabled
If devservices is enabled or not. (default: true)
devservices.image-name
The container image name to use instead of the default one.
(default: docker.io/vectorized/redpanda:v21.5.5)
devservices.port
Optional xed port the dev service will listen to. If not de ned, the
port will be chosen randomly.
devservices.shared
Indicates if the Kafka broker managed by Quarkus Dev Services
is shared. When shared, Quarkus looks for running containers
using label-based service discovery. (default: true)
devservices.service-name
The value of the quarkus-dev-service-kafka label attached to the
started container. (default: kafka)
devservices.topic-partitions-timeout
Timeout for admin client calls used in topic creation. (default:
2S)
devservices.topic-partitions
The topic-partition pairs to create in the Dev Services Kafka
broker. Example: quarkus.kafka.devservices.topic-
partitions.test=2 will create a topic named test with 2 partitions
Apicurio Registry Avro
You can use Apicurio Registry Avro.
./mvnw quarkus:add-extension
-Dextensions="apicurio-registry-avro"
Place schemas at src/main/avro/ directory.
application.properties
mp.messaging.outgoing.movies.connector=smallrye-kafka
mp.messaging.outgoing.movies.topic=movies
# automatically register the schema with the registry, if n
ot present
mp.messaging.outgoing.movies.apicurio.registry.auto-registe
r=true
# URL of registry
mp.messaging.connector.smallrye-kafka.schema.registry.url=h
ttp://localhost:8081
DevServices
When testing or running in dev mode Quarkus can even provide you
with a zero con g Apicurio Registry out of the box.
Possible con guration values pre xed with quarkus.apicurio-
registry:
devservices.enabled
If devservices is enabled or not. (default: true)
devservices.image-name
The container image name to use instead of the default one.
(default: docker.io/apicurio/apicurio-registry-mem:2.1.3.Final)
devservices.port
Optional xed port the dev service will listen to. If not de ned, the
port will be chosen randomly.
devservices.shared
Indicates if the Apicurio managed by Quarkus Dev Services is
shared. When shared, Quarkus looks for running containers using
label-based service discovery. (default: true)
devservices.service-name
The value of the quarkus-dev-service-apicurio-registry label
attached to the started container. (default: apicurio-registry)
AMQP
To integrate with AMQP you need to add next extensions:
./mvnw quarkus:add-extension
-Dextensions="reactive-messaging-amqp"
Then @Outgoing, @Incoming or @Stream can be used.
AMQP con guration schema: mp.messaging.[outgoing|incoming].
{stream-name}.<property>=<value>. Special properties amqp-username
and amqp-password are used to con gure AMQP broker credentials.
The connector type is smallrye-amqp.
amqp-username=quarkus
amqp-password=quarkus
# write
mp.messaging.outgoing.generated-price.connector=
smallrye-amqp
mp.messaging.outgoing.generated-price.address=
prices
mp.messaging.outgoing.generated-price.durable=
true
# read
mp.messaging.incoming.prices.connector=
smallrye-amqp
mp.messaging.incoming.prices.durable=
true
A complete list of supported properties for AMQP.
DevServices
When testing or running in dev mode Quarkus can even provide you
with a zero con g AMQP out of the box.
Possible con guration values pre xed with quarkus.amqp:
devservices.enabled
If devservices is enabled or not. (default: true)
devservices.image-name
The container image name to use instead of the default one.
(default: quay.io/artemiscloud/activemq-artemis-broker:0.1.2)
devservices.port
Optional xed port the dev service will listen to. If not de ned, the
port will be chosen randomly.
The value of the AMQ_EXTRA_ARGS environment variable to pass to
the container. (default: --no-autotune --mapped --no-fsync)
devservices.shared
Indicates if the AMQP broker managed by Quarkus Dev Services
is shared. When shared, Quarkus looks for running containers
using label-based service discovery. (default: true)
devservices.service-name
The value of the quarkus-dev-service-aqmp label attached to the
started container. (default: amqp)
RabbitMQ
To integrate with RabbitMQ you need to add next extensions:
./mvnw quarkus:add-extension
-Dextensions="smallrye-reactive-messaging-rabbitmq"
Then @Outgoing, @Incoming or @Stream can be used.
The connector type is smallrye-rabbitmq.
RabbitMQ con guration schema: mp.messaging.[outgoing|incoming].
{stream-name}.<property>=<value>.
mp.messaging.incoming.requests.connector=smallrye-rabbitmq
mp.messaging.incoming.requests.queue.name=quote-requests
mp.messaging.incoming.requests.exchange.name=quote-requests
mp.messaging.outgoing.quotes.connector=smallrye-rabbitmq
mp.messaging.outgoing.quotes.exchange.name=quotes
A complete list of supported properties for RabbitMQ.
DevServices
When testing or running in dev mode Quarkus can even provide you
with a zero con g RabbitMQ out of the box.
Possible con guration values pre xed with quarkus.rabbitmq:
devservices.enabled
If devservices is enabled or not. (default: true)
devservices.image-name
The container image name to use instead of the default one.
(default: quay.io/kiegroup/kogito-data-index-ephemeral)
devservices.port
Optional xed port the dev service will listen to. If not de ned, the
port will be chosen randomly.
devservices.shared
Indicates if the RabbitMQ managed by Quarkus Dev Services is
shared. When shared, Quarkus looks for running containers using
label-based service discovery. (default: true)
devservices.service-name
The value of the quarkus-dev-service-rabbitmq label attached to
the started container. (default: rabbitmq)
devservices.exchanges.<exchanges>.type
Type of exchange: direct, topic, headers, fanout, etc. (default:
direct)
devservices.exchanges.<exchanges>.auto-delete
Should the exchange be deleted when all queues are nished
using it? (default: false)
devservices.exchanges.<exchanges>.durable
Should the exchange remain after restarts?
devservices.exchanges.<exchanges>.arguments
Extra arguments for the exchange de nition.
devservices.queues.<queues>.auto-delete
Should the queue be deleted when all consumers are nished
using it? (default: false)
devservices.queues.<queues>.durable
Should the queue remain after restarts? (default: false)
devservices.queues.<queues>.arguments
Extra arguments for the queue de nition
devservices.bindings.<bindings>.source
Source exchange to bind to. Defaults to name of binding instance
devservices.bindings.<bindings>.routing-key
Routing key speci cation for the source exchange (default: #)
devservices.bindings.<bindings>.destination
Destination exchange or queue to bind to. Defaults to name of
binding instance
devservices.bindings.<bindings>.destination-type
Destination type for binding: queue, exchange, etc. (default:
queue)
devservices.bindings.<bindings>.arguments
Extra arguments for the binding de nition
MQTT
To integrate with MQTT you need to add next extensions:
./mvnw quarkus:add-extension
-Dextensions="vertx, smallrye-reactive-streams-operator
s
smallrye-reactive-messaging"
And add io.smallrye.reactive:smallrye-reactive-messaging-mqtt-
1.0:0.0.10 dependency in your build tool.
Then @Outgoing, @Incoming or @Stream can be used.
MQTT con guration schema: mp.messaging.[outgoing|incoming].
{stream-name}.<property>=<value>.
The connector type is smallrye-mqtt.
mp.messaging.outgoing.topic-price.type=
smallrye-mqtt
mp.messaging.outgoing.topic-price.topic=
prices
mp.messaging.outgoing.topic-price.host=
localhost
mp.messaging.outgoing.topic-price.port=
1883
mp.messaging.outgoing.topic-price.auto-generated-client-id=
true
mp.messaging.incoming.prices.type=
smallrye-mqtt
mp.messaging.incoming.prices.topic=
prices
mp.messaging.incoming.prices.host=
localhost
mp.messaging.incoming.prices.port=
1883
mp.messaging.incoming.prices.auto-generated-client-id=
true
Kafka Streams
Create streaming queries with the Kafka Streams API.
./mvnw quarkus:add-extension
-Dextensions="kafka-streams"
All we need to do for that is to declare a CDI producer method
which returns the Kafka Streams
org.apache.kafka.streams.Topology:
@ApplicationScoped
public class TopologyProducer {
@Produces
public Topology buildTopology() {
org.apache.kafka.streams.StreamsBuilder.StreamsBuil
der
builder = new StreamsBuilder();
// ...
builder.stream()
.join()
// ...
.toStream()
.to();
return builder.build();
}
}
Previous example produces content to another stream. If you want
to write interactive queries, you can use Kafka streams.
@Inject
KafkaStreams streams;
return streams
.store("stream", QueryableStoreTypes.keyValueStore
());
The Kafka Streams extension is con gured via the Quarkus
con guration le application.properties.
quarkus.kafka-streams.bootstrap-servers=localhost:9092
quarkus.kafka-streams.application-id=temperature-aggregator
quarkus.kafka-streams.application-server=${hostname}:8080
quarkus.kafka-streams.topics=weather-stations,temperature-v
alues
kafka-streams.cache.max.bytes.buffering=10240
kafka-streams.commit.interval.ms=1000
IMPORTANT: All the properties within the kafka-streams
namespace are passed through as-is to the Kafka Streams engine.
Changing their values requires a rebuild of the application.
Reactive DataSource Properties
Common Reeactive DataSource Client con guration properties
pre xed with quarkus.datasource:
reactive.cache-prepared-statements
Prepared statements should be cached on the client side.
(default: false)
reactive.url
The datasource URL.
reactive.max-size
The datasource pool maximum size.
reactive.trust-all
All server certi cates should be trusted. (default: false)
reactive.trust-certificate-pem
Trust con guration in the PEM format.
reactive.trust-certificate-jks
Trust con guration in the JKS format.
reactive.trust-certificate-pfx
Trust con guration in the PFX format.
reactive.key-certificate-pem
Key/cert con guration in the PEM format.
reactive.key-certificate-jks
Key/cert con guration in the JKS format.
reactive.key-certificate-pfx
Key/cert con guration in the PFX format.
reactive.thread-local
Use one connection pool per thread.
reactive.reconnect-attempts
The number of reconnection attempts when a pooled connection
cannot be established on rst try. (default: 0)
reactive.reconnect-interval
The interval between reconnection attempts when a pooled
connection cannot be established on rst try. (default: PT1S)
reactive.idle-timeout
The maximum time without data written to or read from a
connection before it is removed from the pool.
Reactive PostgreSQL Client
You can use Reactive PostgreSQL to execute queries to PostreSQL
database in a reactive way, instead of using JDBC way.
./mvnw quarkus:add-extension
-Dextensions="quarkus-reactive-pg-client"
Database con guration is the same as shown in Persistence
section, but URL is different as it is not a jdbc.
quarkus.datasource.db-kind=postgresql
quarkus.datasource.reactive.url=postgresql:///your_database
Then you can inject io.vertx.mutiny.pgclient.PgPool class.
@Inject
PgPool client;
Uni<List<Fruit>> fruits =
client.preparedQuery("SELECT * FROM fruits")
.onItem().apply(rowSet -> {
JsonArray jsonArray = new JsonArray();
for (Row row : rowSet) {
jsonArray.add(from(row));
}
return jsonArray;
})
Reactive MySQL Client
You can use Reactive MySQL to execute queries to MySQL
database in a reactive way, instead of using JDBC.
./mvnw quarkus:add-extension
-Dextensions="quarkus-reactive-mysql-client"
Database con guration is the same as shown in Persistence
section, but URL is different as it is not a jdbc.
quarkus.datasource.db-kind=mysql
quarkus.datasource.reactive.url=mysql:///your_database
Then you can inject io.vertx.mutiny.mysqlclient.MySQLPool class.
Reactive DB2 Client
You can use Reactive DB2 to execute queries to DB2 database in a
reactive way, instead of using JDBC.
./mvnw quarkus:add-extension
-Dextensions="quarkus-reactive-db2-client"
Database con guration is the same as shown in Persistence
section, but URL is different as it is not a jdbc.
quarkus.datasource.db-kind=db2
quarkus.datasource.reactive.url=vertx-reactive:db2://localh
ost:50005/hreact
Then you can inject io.vertx.mutiny.db2client.DB2Pool class.
Reactive Transactions
io.vertx.mutiny.sqlclient.SqlClientHelper is an util class that
allows you to run reactive persisten code within a transaction.
Uni<Void> r = SqlClientHelper.inTransactionUni(client, tx -
> {
Uni<RowSet<Row>> insertOne = tx.preparedQuery("INSE
RT INTO fruits (name) VALUES ($1) RETURNING (id)")
.execute(Tuple.of(fruit1.name));
});
ActiveMQ Artemis
Quarkus uses Reactive Messaging to integrate with messaging
systems, but in case you need deeper control when using Apache
ActiveMQ Artemis there is also an extension:
./mvnw quarkus:add-extension
-Dextensions="quarkus-artemis-core"
And then you can inject
org.apache.activemq.artemis.api.core.client.ServerLocator
instance.
@ApplicationScoped
public class ArtemisConsumerManager {
@Inject
ServerLocator serverLocator;
private ClientSessionFactory connection;
@PostConstruct
public void init() throws Exception {
connection = serverLocator.createSessionFactory();
}
}
And con gure ServerLocator in application.properties:
quarkus.artemis.url=tcp://localhost:61616
You can con gure ActiveMQ Artemis in application.properties le
by using next properties pre xed with quarkus:
artemis.url
Connection URL.
artemis.username
Username for authentication.
artemis.password
Password for authentication.
Artemis JMS
If you want to use JMS with Artemis, you can do it by using its
extension:
./mvnw quarkus:add-extension
-Dextensions="quarkus-artemis-jms"
And then you can inject javax.jms.ConnectionFactory:
@ApplicationScoped
public class ArtemisConsumerManager {
@Inject
ConnectionFactory connectionFactory;
private Connection connection;
@PostConstruct
public void init() throws JMSException {
connection = connectionFactory.createConnection();
connection.start();
}
}
Con guration options are the same as Artemis core.
Vert.X Reactive Clients
Vert.X Reactive clients in Quarkus, the next clients are supported
and you need to add the dependency to use them:
Vert.X Mail Client
io.smallrye.reactive:smallrye-mutiny-vertx-mail-client
Vert.X MongoDB Client
io.smallrye.reactive:smallrye-mutiny-vertx-mongo-client
Vert.X Redis Client
io.smallrye.reactive:smallrye-mutiny-vertx-redis-client
Vert.X Cassandra Client
io.smallrye.reactive:smallrye-mutiny-vertx-cassandra-client
Vert.X Consul Client
io.smallrye.reactive:smallrye-mutiny-vertx-consul-client
Vert.X Kafka Client
io.smallrye.reactive:smallrye-mutiny-vertx-kafka-client
Vert.X AMQP Client
io.smallrye.reactive:smallrye-mutiny-vertx-amqp-client
Vert.X RabbitMQ Client
io.smallrye.reactive:smallrye-mutiny-vertx-rabbitmq-client
Example of Vert.X Web Client:
@Inject
Vertx vertx;
private WebClient client;
@PostConstruct
void initialize() {
this.client = WebClient.create(vertx, ...);
}
Amazon SQS Client
./mvnw quarkus:add-extension
-Dextensions="amazon-sqs"
Injecting the client:
@Inject
software.amazon.awssdk.services.sqs.SqsClient sqs;
SendMessageResponse response = sqs.sendMessage(m -> m.queue
Url(queueUrl).messageBody(message));
List<Message> messages = sqs.receiveMessage(m -> m.maxNumbe
rOfMessages(10).queueUrl(queueUrl)).messages();
And con gure it:
quarkus.sqs.endpoint-override=http://localhost:8010
quarkus.sqs.aws.region=us-east-1
quarkus.sqs.aws.credentials.type=static
quarkus.sqs.aws.credentials.static-provider.access-key-id=t
est-key
quarkus.sqs.aws.credentials.static-provider.secret-access-k
ey=test-secret
You need to set a HTTP client either URL Connection:
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>url-connection-client</artifactId>
</dependency>
or Apache HTTP:
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>apache-client</artifactId>
</dependency>
quarkus.sqs.sync-client.type=apache
You can go async by using Mutiny:
@Inject
software.amazon.awssdk.services.sqs.SqsAsyncClient sqs;
Uni.createFrom()
.completionStage(
sqs.sendMessage(m -> m.queueUrl(queueUrl).messageBo
dy(message))
)
.onItem()...
return Uni.createFrom()
.completionStage(
sqs.receiveMessage(m -> m.maxNumberOfMessages(10).q
ueueUrl(queueUrl))
)
.onItem()
And you need to add the asynchronous Netty client:
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>netty-nio-client</artifactId>
</dependency>
Con guration properties are the same as Amazon DynamoDB but
changing the pre x from dynamodb to sqs.
TLS
You can trust all certi cates globally by using quarkus.tls.trust-
all=true
RBAC
You can set RBAC using annotations or in application.properties.
Annotations
You can de ne roles by using
javax.annotation.security.RolesAllowed annotation.
@RolesAllowed("Subscriber")
You can use io.quarkus.security.Authenticated as a shortcut of
@RolesAllowed("*").
To alter RBAC behaviour there are two con guration properties:
quarkus.security.deny-unannotated=true
Con guration options:
quarkus.jaxrs.deny-uncovered
If true denies by default to all JAX-RS endpoints. (default: false)
quarkus.security.deny-unannotated
If true denies by default all CDI methods and JAX-RS endpoints.
(default: false)
By default in Quarkus, if an incoming request has a credential the
request will always be authenticated (even if the target page does
not require authentication).
You can change this behaviour by setting
quarkus.http.auth.proactive property to false.
File Con guration
De ning RBAC in application.properties instead of using
annotations.
quarkus.http.auth.policy.role-policy1.roles-allowed=
user,admin
quarkus.http.auth.permission.roles1.paths=
/roles-secured/*,/other/*,/api/*
quarkus.http.auth.permission.roles1.policy=
role-policy1
quarkus.http.auth.permission.permit1.paths=
/public/*
quarkus.http.auth.permission.permit1.policy=
permit
quarkus.http.auth.permission.permit1.methods=
GET
quarkus.http.auth.permission.deny1.paths=
/forbidden
quarkus.http.auth.permission.deny1.policy=
deny
You need to provide permissions set by using the roles-allowed
property or use the built-in ones deny, permit or authenticated.
You can use enabled property (ie
quarkus.http.auth.permission.permit1.enabled) to enable the entire
permission set.
Testing
Quarkus provides explicit support for testing with different users,
and with the security subsystem disabled.
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-test-security</artifactId>
<scope>test</scope>
</dependency>
@Test
@TestSecurity(authorizationEnabled = false)
void someTestMethod() {
...
}
@Test
@TestSecurity(user = "testUser", roles = {"admin", "user"})
void someTestMethod() {
...
}
BouncyCastle
Quarkus supports BouncyCastle, you only need to add the
BouncyCastle dependency and con gure the security provider:
quarkus.security.security-providers=BC
quarkus.security.security-providers=BCJSSE
quarkus.security.security-providers=BCFIPS
quarkus.security.security-providers=BCFIPSJSSE
JWT
Quarkus implements MicroPro le JWT RBAC spec.
mvn quarkus:add-extension
-Dextensions="io.quarkus:quarkus-smallrye-jwt"
Minimum JWT required claims: typ, alg, kid, iss, sub, exp, iat,
jti, upn, groups.
You can inject token by using JsonWebToken or a claim individually by
using @Claim.
@Inject
JsonWebToken jwt;
@Inject
@Claim(standard = Claims.preferred_username)
String name;
@Inject
@Claim("groups")
Set<String> groups;
@Inject
JWTParser parser;
Set of supported types: String, Set<String>, Long, Boolean,
`javax.json.JsonValue, Optional,
org.eclipse.microprofile.jwt.ClaimValue.
And con guration in src/main/resources/application.properties:
mp.jwt.verify.publickey.location=
META-INF/resources/publicKey.pem
mp.jwt.verify.issuer=
https://quarkus.io/using-jwt-rbac
Con guration options:
mp.jwt.verify.publickey
Public Key text itself to be supplied as a string.
mp.jwt.verify.publickey.location Relative path or URL of a public
key.
mp.jwt.verify.issuer
iss accepted as valid.
smallrye.jwt.token.header
Sets header such as Cookie is used to pass the token. (default:
Authorization).
smallrye.jwt.token.cookie
Name of the cookie containing a token.
smallrye.jwt.token.schemes
Comma-separated list containing an alternative single or multiple
schemes. (default: Bearer).
smallrye.jwt.require.named-principal
A token must have a upn or preferred_username or sub claim set
if using java.security.Principal. True makes throw an exception
if not set. (default: false).
smallrye.jwt.path.sub
Path to the claim with subject name.
smallrye.jwt.claims.sub
Default sub claim value.
smallrye.jwt.path.groups
Path to the claim containing the groups.
smallrye.jwt.groups-separator
Separator for splitting a string which may contain multiple group
values. (default. ` `).
smallrye.jwt.claims.groups
Default groups claim value.
smallrye.jwt.jwks.refresh-interval
JWK cache refresh interval in minutes. (default: 60).
smallrye.jwt.expiration.grace
Expiration grace in seconds. (default: 60).
smallrye.jwt.verify.aud
Comma separated list of the audiences that a token aud claim
may contain.
smallrye.jwt.verify.algorithm
Signature algorith. (defsult: RS256)
smallrye.jwt.token.kid
If set then the veri cation JWK key as well every JWT token must
have a matching kid header.
smallrye.jwt.time-to-live
The maximum number of seconds that a JWT may be issued for
use.
smallrye.jwt.sign.key-location
Location of a private key which will be used to sign the claims
when either a no-argument sign() or innerSign() method is
called.
smallrye.jwt.encrypt.key-location
Location of a public key which will be used to encrypt the claims
or inner JWT when a no-argument encrypt() method is called.
Supported public key formats:
PKCS#8 PEM
JWK
JWKS
JWK Base64 URL
JWKS Base64 URL
To send a token to server-side you should use Authorization
header: curl -H "Authorization: Bearer eyJraWQiOi…".
To inject claim values, the bean must be @RequestScoped CDI
scoped. If you need to inject claim values in scope with a lifetime
greater than @RequestScoped then you need to use
javax.enterprise.inject.Instance interface.
@Inject
@Claim(standard = Claims.iat)
private Instance<Long> providerIAT;
RBAC
JWT groups claim is directly mapped to roles to be used in security
annotations.
@RolesAllowed("Subscriber")
Testing
You can use @TestSecurity annotation tooin OIDC by registering the
following dependency:
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-test-security-jwt</artifactId>
<scope>test</scope>
</dependency>
@Test
@TestSecurity(user = "userJwt", roles = "viewer")
@JwtSecurity(claims = {
@Claim(key = "email", value = "user@gmail.com")
})
public void testJwtWithClaims() {}
Generate tokens
JWT generation API:
Jwt.claims()
.issuer("https://server.com")
.claim("customClaim", 3)
.sign(createKey());
JwtSignatureBuilder jwtSignatureBuilder = Jwt.claims("/test
JsonToken.json").jws();
jwtSignatureBuilder
.signatureKeyId("some-key-id")
.signatureAlgorithm(SignatureAlgorithm.ES256)
.header("custom-header", "custom-value");
.sign(createKey());
Jwt.claims("/testJsonToken.json")
.encrypt(createKey());
JwtEncryptionBuilder jwtEncryptionBuilder = Jwt.claims("/te
stJsonToken.json").jwe();
jwtEncryptionBuilder
.keyEncryptionKeyId("some-key-id")
.keyEncryptionAlgorithm(KeyEncryptionAlgorithm.ECDH_E
S_A256KW)
.header("custom-header", "custom-value");
.encrypt(createKey());
Jwt.claims("/testJsonToken.json")
.innerSign(createKey());
.encrypt(createKey());
OpenId Connect
Quarkus can use OpenId Connect or OAuth 2.0 authorization
servers such as Keycloak to protect resources using bearer token
issued by Keycloak server.
mvn quarkus:add-extension
-Dextensions="using-openid-connect"
You can also protect resources with security annotations.
@GET
@RolesAllowed("admin")
You can inject the folowing Oidc objects in a class:
@Inject
io.quarkus.oidc.UserInfo userInfo;
@Inject
io.quarkus.oidc.OidcConfigurationMetadata configMetadata;
Con gure application to Keycloak service in application.properties
le.
quarkus.oidc.realm=quarkus
quarkus.oidc.auth-server-url=http://localhost:8180/auth
quarkus.oidc.resource=backend-service
quarkus.oidc.bearer-only=true
quarkus.oidc.credentials.secret=secret
quarkus-oidc-client can be con gured as follows to support MTLS:
quarkus.oidc.tls.verification=certificate-validation
quarkus.oidc.client.tls.key-store-file=client-keystore.jks
quarkus.oidc.client.tls.key-store-password=${key-store-pass
word}
quarkus.oidc.client.tls.key-store-alias=keyAlias
quarkus.oidc.client.tls.key-store-alias-password=keyAliasPa
ssword
quarkus.oidc.client.tls.trust-store-file=client-truststore.
jks
quarkus.oidc.client.tls.trust-store-password=${trust-store-
password}
quarkus.oidc.client.tls.trust-store-alias=certAlias
There is also support for the public OIDC providers:
GitHub
quarkus.oidc.provider=github
quarkus.oidc.client-id=github_app_clientid
quarkus.oidc.credentials.secret=github_app_clientsecret
Apple
quarkus.oidc.provider=apple
quarkus.oidc.client-id=${apple.client-id}
quarkus.oidc.credentials.jwt.token-key-id=${apple.key-id}
Google
quarkus.oidc.provider=google
quarkus.oidc.client-id={GOOGLE_CLIENT_ID}
quarkus.oidc.credentials.secret={GOOGLE_CLIENT_SECRET}
quarkus.oidc.token.issuer=https://accounts.google.com
Con guration options with quarkus.oidc pre x:
enabled
The OIDC is enabled. (default: true)
tenant-enabled
If the tenant con guration is enabled. (default: true)
The application type. Possible values: web_app, service. (default:
service)
connection-delay
The maximum amount of time the adapter will try connecting.
auth-server-url
The base URL of the OpenID Connect (OIDC) server.
introspection-path
Relative path of the RFC7662 introspection service.
jwks-path
Relative path of the OIDC service returning a JWK set.
public-key
Public key for the local JWT token veri cation
client-id
The client-id of the application.
roles.role-claim-path
Path to the claim containing an array of groups. (realm/groups)
roles.role-claim-separator
Separator for splitting a string which may contain multiple group
values.
token.issuer
Issuer claim value.
token.audience
Audience claim value.
token.expiration-grace
Expiration grace period in seconds.
token.principal-claim
Name of the claim which contains a principal name.
token.refresh-expired
If property is enabled then a refresh token request is performed.
credentials.secret
The client secret
authentication.redirect-path
Relative path for calculating a redirect_uri query parameter.
authentication.restore-path-after-redirect
The original request URI used before the authentication will be
restored after the user has been redirected back to the
application. (default: true)
authentication.force-redirect-https-scheme
Force 'https' as the 'redirect_uri' parameter scheme when running
behind an SSL terminating reverse proxy.
authentication.scopes
List of scopes.
authentication.extra-params
Additional properties which will be added as the query
parameters .
authentication.cookie-path
Cookie path parameter.
proxy.host
The host (name or IP address) of the Proxy.
proxy.port
The port number of the Proxy. (default: 80)
proxy.username
The username to authenticate.
proxy.password
The password to authenticate.
end-session-path
Relative path of the OIDC end_session_endpoint.
logout.path
The relative path of the logout endpoint at the application.
logout.post-logout-path
Relative path of the application endpoint where the user should
be redirected to after logging out.
tls.verification
Sets the TLs veri cation. Possible values: REQUIRED, NONE.
(default: REQUIRED).
With Keycloak OIDC server
https://host:port/auth/realms/{realm} where {realm} has
to be replaced by the name of the Keycloak realm.
You can use quarkus.http.cors property to enable
consuming form different domain.
Testing
You can use @TestSecurity annotation tooin OIDC by registering the
following dependency:
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-test-security-oidc</artifactId>
<scope>test</scope>
</dependency>
@Test
@TestSecurity(user = "userOidc", roles = "viewer")
@OidcSecurity(claims = {
@Claim(key = "email", value = "user@gmail.com")
}, userinfo = {
@UserInfo(key = "sub", value = "subject")
}, config = {
@ConfigMetadata(key = "issuer", value = "issuer")
})
public void testOidcWithClaimsUserInfoAndMetadata() {}
DevServices
When testing or running in dev mode Quarkus can even provide you
with a zero con g Keycloak out of the box.
Possible con guration values pre xed with quarkus.keycloak:
devservices.enabled
If devservices is enabled or not. (default: true)
devservices.image-name
The container image name to use instead of the default one.
Keycloak-X can be used (quay.io/keycloak/keycloak-x:15.0.2)
(default: quay.io/keycloak/keycloak:15.0.2)
devservices.keycloak-x-image
Set quarkus.devservices.keycloak.keycloak-x-image to override
this check which may be necessary if you build custom Keycloak-
X or Keycloak images. You do not need to set this property if the
default check works.
devservices.port
Optional xed port the dev service will listen to. If not de ned, the
port will be chosen randomly.
devservices.shared
Indicates if the Keycloak broker managed by Quarkus Dev
Services is shared. When shared, Quarkus looks for running
containers using label-based service discovery. (default: true)
devservices.service-name
The value of the quarkus-dev-service-keycloak label attached to
the started container. (default: kafka)
devservices.realm-path
The class or le system path to a Keycloak realm le which will
be used to initialize Keycloak
devservices.java-opts
The JAVA_OPTS passed to the keycloak JVM
devservices.realm-name
The Keycloak realm name
devservices.create-realm
Indicates if the Keycloak realm has to be created when the realm
le pointed to by the 'realm-path' property does not exist
devservices.users
The Keycloak users map containing the user name and password
pairs
devservices.roles
The Keycloak user roles
Multi-tenancy
Multi-tenancy is supported by adding a sub-category to OIDC
con guration properties (ie quarkus.oidc.{tenent_id}.property).
quarkus.oidc.auth-server-url=http://localhost:8180/auth/rea
lms/quarkus
quarkus.oidc.client-id=multi-tenant-client
quarkus.oidc.application-type=web-app
quarkus.oidc.tenant-b.auth-server-url=https://accounts.goog
le.com
quarkus.oidc.tenant-b.application-type=web-app
quarkus.oidc.tenant-b.client-id=xxxx
quarkus.oidc.tenant-b.credentials.secret=yyyy
quarkus.oidc.tenant-b.token.issuer=https://accounts.google.
com
quarkus.oidc.tenant-b.authentication.scopes=email,profile,o
penid
You can inject io.quarkus.oidc.client.Tokens,
io.quarkus.oidc.OidcSession, and io.quarkus.oidc.client.OidcClient
to interact with OIDC.
@Inject
@io.quarkus.oidc.client.NamedOidcClient("client2")
OidcClient client;
@Inject
@io.quarkus.oidc.client.NamedOidcClient("client1")
Tokens tokens1;
@Inject
OidcSession oidcSession;
OAuth2
Quarkus integrates with OAuth2 to be used in case of opaque
tokens (none JWT) and its validation against an introspection
endpoint.
mvn quarkus:add-extension
-Dextensions="security-oauth2"
And con guration in src/main/resources/application.properties:
quarkus.oauth2.client-id=client_id
quarkus.oauth2.client-secret=secret
quarkus.oauth2.introspection-url=http://oauth-server/intros
pect
And you can map roles to be used in security annotations.
@RolesAllowed("Subscriber")
Con guration options:
quarkus.oauth2.enabled
Determine if the OAuth2 extension is enabled. (default: true)
quarkus.oauth2.client-id
The OAuth2 client id used to validate the token.
quarkus.oauth2.client-secret
The OAuth2 client secret used to validate the token.
quarkus.oauth2.introspection-url
URL used to validate the token and gather the authentication
claims.
quarkus.oauth2.role-claim
The claim that is used in the endpoint response to load the roles
((default: scope)
Authenticating via HTTP
HTTP basic auth is enabled by the quarkus.http.auth.basic=true
property.
HTTP form auth is enabled by the
quarkus.http.auth.form.enabled=true property.
Then you need to add elytron-security-properties-file or elytron-
security-jdbc.
Security with Properties File
You can also protect endpoints and store identities (user, roles) in
the le system.
mvn quarkus:add-extension
-Dextensions="elytron-security-properties-file"
You need to con gure the extension with users and roles les:
And con guration in src/main/resources/application.properties:
quarkus.security.users.file.enabled=true
quarkus.security.users.file.users=test-users.properties
quarkus.security.users.file.roles=test-roles.properties
quarkus.security.users.file.auth-mechanism=BASIC
quarkus.security.users.file.realm-name=MyRealm
quarkus.security.users.file.plain-text=true
Then users.properties and roles.properties:
scott=jb0ss
jdoe=p4ssw0rd
scott=Admin,admin,Tester,user
jdoe=NoRolesUser
IMPORTANT: If plain-text is set to false (or omitted) then
passwords must be stored in the form MD5
(username:`realm`:`password`).
Elytron File Properties con guration properties. Pre x
quarkus.security.users is skipped.
file.enabled
The le realm is enabled. (default: false)
file.auth-mechanism
The authentication mechanism. ( default: BASIC)
file.realm-name
The authentication realm name. (default: Quarkus)
file.plain-text
If passwords are in plain or in MD5. (default: false)
file.users
Classpath resource of user/password. (default:
users.properties)
file.roles
Classpath resource of user/role. (default: roles.properties)
Embedded Realm
You can embed user/password/role in the same
application.properties:
quarkus.security.users.embedded.enabled=true
quarkus.security.users.embedded.plain-text=true
quarkus.security.users.embedded.users.scott=jb0ss
quarkus.security.users.embedded.roles.scott=admin,tester,us
er
quarkus.security.users.embedded.auth-mechanism=BASIC
IMPORTANT: If plain-text is set to false (or omitted) then
passwords must be stored in the form MD5
(username:`realm`:`password`).
Pre x quarkus.security.users.embedded is skipped.
algorithm
Determine which algorithm to use. Possible values: DIGEST_MD5,
DIGEST_SHA, DIGEST_SHA_256, DIGEST_SHA_384, DIGEST_SHA_512,
DIGEST_SHA_512_256. (default: DIGEST_MD5)
file.enabled
The le realm is enabled. (default: false)
file.auth-mechanism
The authentication mechanism. (default: BASIC)
file.realm-name
The authentication realm name. (default: Quarkus)
file.plain-text
If passwords are in plain or in MD5. (default: false)
file.users.*
* is user and value is password.
file.roles.*
* is user and value is role.
Security with a JDBC Realm
You can also protect endpoints and store identities in a database.
mvn quarkus:add-extension
-Dextensions="elytron-security-jdbc"
You still need to add the database driver (ie jdbc-h2).
You need to con gure JDBC and Elytron JDBC Realm:
quarkus.datasource.url=
quarkus.datasource.driver=org.h2.Driver
quarkus.datasource.username=sa
quarkus.datasource.password=sa
quarkus.security.jdbc.enabled=true
quarkus.security.jdbc.principal-query.sql=
SELECT u.password, u.role FROM test_user u WHERE u.user
=?
quarkus.security.jdbc.principal-query
.clear-password-mapper.enabled=true
quarkus.security.jdbc.principal-query
.clear-password-mapper.password-index=1
quarkus.security.jdbc.principal-query
.attribute-mappings.0.index=2
quarkus.security.jdbc.principal-query
.attribute-mappings.0.to=groups
You need to set the index (1-based) of password and role.
Elytron JDBC Realm con guration properties. Pre x
quarkus.security.jdbc is skipped.
auth-mechanism
The authentication mechanism. (default: BASIC)
realm-name
The authentication realm name. (default: Quarkus)
bl d
If the properties store is enabled. (default: false)
principal-query.sql
The sql query to nd the password.
principal-query.datasource
The data source to use.
principal-query.clear-password-mapper.enabled
If the clear-password-mapper is enabled. (default: false)
principal-query.clear-password-mapper.password-index
The index of column containing clear password. (default: 1)
principal-query.bcrypt-password-mapper.enabled
If the bcrypt-password-mapper is enabled. (default: false)
principal-query.bcrypt-password-mapper.password-index
The index of column containing password hash. (default: 0)
principal-query.bcrypt-password-mapper.hash-encoding
A string referencing the password hash encoding (BASE64 or HEX).
(default: BASE64)
principal-query.bcrypt-password-mapper.salt-index
The index column containing the Bcrypt salt. (default: 0)
principal-query.bcrypt-password-mapper.salt-encoding
A string referencing the salt encoding (BASE64 or HEX). (default:
BASE64)
principal-query.bcrypt-password-mapper.iteration-count-index
The index column containing the Bcrypt iteration count. (default:
0)
For multiple datasources you can use the datasource name in the
properties:
quarkus.datasource.url=
quarkus.security.jdbc.principal-query.sql=
quarkus.datasource.permissions.url=
quarkus.security.jdbc.principal-query.permissions.sql=
Security with JPA
You can also protect endpoints and store identities in a database
using JPA.
mvn quarkus:add-extension
-Dextensions="security-jpa"
Also you might require jdbc-postgresql, resteasy,
hibernate-orm-panache.
@io.quarkus.security.jpa.UserDefinition
@Table(name = "test_user")
@Entity
public class User extends PanacheEntity {
@io.quarkus.security.Username
public String name;
@io.quarkus.security.Password
public String pass;
@ManyToMany
@Roles
public List<Role> roles = new ArrayList<>();
public static void add(String username, String passwor
d) {
User user = new User();
user.username = username;
user.password = BcryptUtil.bcryptHash(password);
user.persist();
}
}
@Entity
public class Role extends PanacheEntity {
@ManyToMany(mappedBy = "roles")
public List<ExternalRolesUserEntity> users;
@io.quarkus.security.RolesValue
public String role;
}
You need to con gure JDBC:
quarkus.datasource.url=jdbc:postgresql:security_jpa
quarkus.datasource.driver=org.postgresql.Driver
quarkus.datasource.username=quarkus
quarkus.datasource.password=quarkus
quarkus.hibernate-orm.database.generation=drop-and-create
Security with LDAP
You can also protect endpoints and store identities in a database
using LDAP.
mvn quarkus:add-extension
-Dextensions="elytron-security-ldap"
quarkus.security.ldap.enabled=true
quarkus.security.ldap.dir-context.principal=uid=tool,ou=acc
ounts,o=YourCompany,c=DE
quarkus.security.ldap.dir-context.url=ldaps://ldap.server.l
ocal
quarkus.security.ldap.dir-context.password=PASSWORD
quarkus.security.ldap.identity-mapping.rdn-identifier=uid
quarkus.security.ldap.identity-mapping.search-base-dn=ou=us
ers,ou=tool,o=YourCompany,c=DE
quarkus.security.ldap.identity-mapping.attribute-mapping
s."0".from=cn
quarkus.security.ldap.identity-mapping.attribute-mapping
s."0".to=groups
quarkus.security.ldap.identity-mapping.attribute-mapping
s."0".filter=(member=uid={0})
quarkus.security.ldap.identity-mapping.attribute-mapping
s."0".filter-base-dn=ou=roles,ou=tool,o=YourCompany,c=DE
Testing
There is a Quarkus Test Resource that starts and stops InMemory
LDAP server before and after test suite. It is running in localhost
with dc=quarkus,dc=io and binding credentials
("uid=admin,ou=system", "secret"). Imports LDIF from a le located
at root of the classpath named quarkus-io.ldif.
Register dependency io.quarkus:quarkus-test-ldap:test.
And annotate the test:
@QuarkusTestResource(io.quarkus.test.ldap.LdapServerTestRes
ource.class)
public class ElytronLdapExtensionTestResources {
}
Elytron LDAP Realm con guration properties. Pre x
quarkus.security.ldap is skipped.
enabled
Enable the LDAP elytron module (default: false)
realm-name
The elytron realm name (default: Quarkus)
direct-verification
Provided credentials are veri ed against LDAP (default: true)
dir-context.url
The url of the LDAP server.
dir-context.principal
User (bindDn) which is used to connect to LDAP server.
dir-context.password
The password (bindCredential) which belongs to the principal.
identity-mapping.rdn-identifier
The identi er (baseFilter) which correlates to the provided user
(default: uid)
identity-mapping.search-base-dn
The dn where we look for users.
identity-mapping.attribute-mappings.<id>.from
The roleAttributeId from which is mapped
identity-mapping.attribute-mappings.<id>.to
The identi er whom the attribute is mapped to (default: gropus)
identity-mapping.attribute-mappings.<id>.filter
The lter (roleFilter)
identity-mapping.attribute-mappings.<id>.filter-base-dn
The lter base dn (rolesContextDn)
Vault
Quarkus integrates with Vault to manage secrets or protecting
sensitive data.
mvn quarkus:add-extension
-Dextensions="vault"
And con guring Vault in application.properties:
# vault url
quarkus.vault.url=http://localhost:8200
quarkus.vault.authentication.userpass.username=
bob
quarkus.vault.authentication.userpass.password=
sinclair
# path within the kv secret engine
quarkus.vault.secret-config-kv-path=
myapps/vault-quickstart/config
quarkus.vault.secret-config-kv-prefix.singer.paths=
multi/singer1, multi/singer2
vault kv put secret/myapps/vault-quickstart/config a-private-
key=123456
vault kv put secret/multi/singer1 firstname=paul
@ConfigProperty(name = "a-private-key")
String privateKey;
@ConfigProperty(name = "singer.firstname")
String firstName;
You can access the KV engine programmatically:
@Inject
VaultKVSecretEngine kvSecretEngine;
kvSecretEngine.readSecret("myapps/vault-quickstart/" + vaul
tPath).toString();
Map<String, String> secrets;
kvSecretEngine.writeSecret("myapps/vault-quickstart/crud",
secrets);
kvSecretEngine.deleteSecret("myapps/vault-quickstart/crud"
);
Fetching credentials DB
With the next kv vault kv put secret/myapps/vault-quickstart/db
password=connor
quarkus.vault.credentials-provider.mydatabase.kv-path=
myapps/vault-quickstart/db
quarkus.datasource.db-kind=
postgresql
quarkus.datasource.username=
sarah
quarkus.datasource.credentials-provider=
mydatabase
quarkus.datasource.jdbc.url=
jdbc:postgresql://localhost:5432/mydatabase
No password is set as it is fetched from Vault.
Dynamic credentials are also supported:
Running the following dynamic database con g in Vault:
vault write database/config/mydb plugin_name=postgresql-database-
plugin …..
You can con gure as:
quarkus.vault.credentials-provider
.mydatabase.database-credentials-role=mydbrole
quarkus.datasource.db-kind=
postgresql
quarkus.datasource.credentials-provider=
mydatabase
quarkus.datasource.jdbc.url=
jdbc:postgresql://localhost:5432/mydatabase
Username and password are fetched from Vault
Transit
@Inject
VaultTransitSecretEngine transit;
transit.encrypt("my_encryption", text);
transit.decrypt("my_encryption", text).asString();
transit.sign("my-sign-key", text);
Transit Key
@Inject
VaultTransitSecretEngine transit;
transit.createKey(KEY_NAME, new KeyCreationRequestDetail().
setExportable(true));
transit.readKey(KEY_NAME);
transit.listKeys();
transit.exportKey(KEY_NAME, VaultTransitExportKeyType.encry
ption, null);
transit.updateKeyConfiguration(KEY_NAME, new KeyConfigReque
stDetail().setDeletionAllowed(true));
transit.deleteKey(KEY_NAME);
Vault TOTP
TOTP secret engine is supported by using
io.quarkus.vault.VaultTOTPSecretEngine class:
@Inject
VaultTOTPSecretEngine vaultTOTPSecretEngine;
CreateKeyParameters createKeyParameters = new CreateKeyPara
meters("Google", "test@gmail.com");
createKeyParameters.setPeriod("30m");
/** Generate Key (QR code) */
final Optional<KeyDefinition> myKey = vaultTOTPSecretEngine
.createKey("my_
key_2", createKeyParameters);
/** Generate key number to login */
final String keyCode = vaultTOTPSecretEngine.generateCode(
"my_key_2");
/** Login logic */
boolean valid = vaultTOTPSecretEngine.validateCode("my_key_
2", keyCode);
Vault Provisioning
Vault extension offers façade classes to Vault provisioning
functions:
@Inject
VaultSystemBackendEngine vaultSystemBackendEngine;
@Inject
VaultKubernetesAuthService vaultKubernetesAuthService;
String rules = "path "transit/*" {n" +
" capabilities = [ "create", "read", "updat
e" ]n" +
"}";
String policyName = "sys-test-policy";
vaultSystemBackendEngine.createUpdatePolicy(policyName, rul
es);
vaultKubernetesAuthService
.createRole(roleName, new VaultKubernetesAuthRole()
.setBoundServiceAccountNames(boundServiceAccountN
ames)
.setBoundServiceAccountNamespaces(boundServiceAcc
ountNamespaces)
.setTokenPolicies(tokenPolicies));
PKI
@Inject
public VaultPKISecretEngine pkiSecretEngine;
GenerateCertificateOptions options = new GenerateCertificat
eOptions();
SignedCertificate signed = pkiSecretEngine.signRequest(
"example-dot-com", csr, options);
return signed.certificate.getData();
Vault con guration properties. Pre x quarkus.vault is skipped.
url
Vault server URL
authentication.client-token
Vault token to access
authentication.app-role.role-id
Role Id for AppRole auth
authentication.app-role.secret-id
Secret Id for AppRole auth
authentication.app-role.secret-id-wrapping-token
Wrapping token containing a Secret Id. secret-id and secret-id-
wrapping-token are exclusive.
authentication.userpass.username
Username for userpass auth
authentication.userpass.password
Password for userpass auth
authentication.userpass.password-wrapping-token
Wrapping token containing a password. password and password-
wrapping-token are exclusive.
authentication.kubernetes.role
Kubernetes authentication role
authentication.kubernetes.jwt-token-path
Location of the le containing the Kubernetes JWT token
renew-grace-period
Renew grace period duration (default: 1H)
secret-config-cache-period
Vault con g source cache period (default: 10M)
secret-config-kv-path
Vault path in kv store. List of paths is supported in CSV
log-confidentiality-level
Used to hide con dential infos. low, medium, high (default:
medium)
kv-secret-engine-version
Kv secret engine version (default: 1)
kv-secret-engine-mount-path Kv secret engine path (default: secret)
tls.skip-verify
Allows to bypass certi cate validation on TLS communications
(default: false)
tls.ca-cert
Certi cate bundle used to validate TLS communications
tls.use-kubernetes-ca-cert
TLS will be active (default: true)
connect-timeout
Tiemout to establish a connection (default: 5S)
read-timeout
Request timeout (default: 1S)
credentials-provider."credentials-provider".database-credentials-
role
Database credentials role
credentials-provider."credentials-provider".kv-path
A path in vault kv store, where we will nd the kv-key
credentials-provider."credentials-provider".kv-key
Key name to search in vault path kv-path (default: password)
DevServices
When testing or running in dev mode Quarkus can even provide you
with a zero con g Vault out of the box.
Possible con guration values are shown at Vault
Amazon KMS
mvn quarkus:add-extension
-Dextensions="amazon-kms"
@Inject
KmsClient kms;
kms.encrypt(req -> req.keyId(keyArn).plaintext(
SdkBytes.fromUtf8String(data))).ciphertextBlob();
quarkus.kms.endpoint-override=http://localhost:8011
quarkus.kms.aws.region=us-east-1
quarkus.kms.aws.credentials.type=static
quarkus.kms.aws.credentials.static-provider.access-key-id=t
est-key
quarkus.kms.aws.credentials.static-provider.secret-access-k
ey=test-secret
You need to set a HTTP client either URL Connection:
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>url-connection-client</artifactId>
</dependency>
or Apache HTTP:
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>apache-client</artifactId>
</dependency>
quarkus.sqs.sync-client.type=apache
You can go async by using Mutiny:
@Inject
software.amazon.awssdk.services.kms.KmsAsyncClient kms;
Uni.createFrom().completionStage(
kms.encrypt(req -> req.keyId(keyArn).plaintext(SdkByte
s.fromUtf8String(data))
))
And you need to add the asynchronous Netty client:
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>netty-nio-client</artifactId>
</dependency>
Con guration properties are the same as Amazon DynamoDB but
changing the pre x from dynamodb to kms.
Amazon IAM
mvn quarkus:add-extension
-Dextensions="quarkus-amazon-iam"
You need to set a HTTP client either URL Connection:
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>url-connection-client</artifactId>
</dependency>
or Apache HTTP:
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>apache-client</artifactId>
</dependency>
And you need to add the asynchronous Netty client:
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>netty-nio-client</artifactId>
</dependency>
@Inject
IamClient client;
@Inject
IamAsyncClient async;
quarkus.iam.endpoint-override=${iam.url}
quarkus.iam.aws.region=us-east-1
quarkus.iam.aws.credentials.type=static
quarkus.iam.aws.credentials.static-provider.access-key-id=t
est-key
quarkus.iam.aws.credentials.static-provider.secret-access-k
ey=test-secret
Con guration properties are the same as Amazon DynamoDB but
changing the pre x from dynamodb to iam.
HTTP Con guration
You can con gure HTTP parameters. Using quarkus.http pre x:
http.access-log.exclude-pattern
A regular expression that can be used to exclude some paths
from logging
cors
Enable CORS. (default: false)
cors.origins
CSV of origins allowed. Regular expressions are also allowed
(dedault: Any request valid.)
cors.methods
CSV of methods valid. (default: Any method valid.)
cors.headers
CSV of valid allowed headers. (default: Any requested header
valid.)
cors.exposed-headers
CSV of valid exposed headers.
port
The HTTP port. (default: 8080)
test-port
The HTTP test port. (default: 8081)
host
The HTTP host. (default: 0.0.0.0)
host-enabled
Enable listening to host:port. (default: true)
ssl-port
The HTTPS port. (default 8443)
test-ssl-port
The HTTPS port used to run tests. (default: 8444)
insecure-requests
If insecure requests are allowed. Possible values: enabled,
redirect, disable. (default: enabled)
http2
Enables HTTP/2. (default: true)
proxy.proxy-address-forwarding
The address, scheme etc will be set from headers forwarded by
the proxy server.
proxy.allow-forwarded
Proxy address forwarding is enabled then the standard Forwarded
header will be used, rather than the more common but not
standard X-Forwarded-For
proxy.enable-forwarded-host
Enable override the received request’s host through a forwarded
host header
proxy.forwarded-host-header
Con gure the forwarded host header to be used if override
enabled
ssl.port
The HTTPS port. (default: 8443)
ssl.certificate.files
The les path to a service certi cate or certi cate chain in PEM
format. Relative to src/main/resources.
ssl.certificate.key-files
The les path to the corresponding certi cate private key in PEM
format. Relative to src/main/resources.
ssl.certificate.key-store-file
The key store contains the certi cate information. Relative to
src/main/resources.
ssl.certificate.key-store-key-alias
An optional parameter to select a speci c key in the key store.
ssl.certificate.key-store-file-type
The key store type. It is automatically detected based on the le
name or can be set manually. Supported values are: JKS, JCEKS,
P12, PKCS12 or PFX.
ssl.certificate.key-store-password
The password to open the key store le.
ssl.certificate.trust-store-file
The trust store location which contains the certi cate
information of the certi cates to trust. Relative to
src/main/resources.
ssl.certificate.trust-store-cert-alias
An optional parameter to trust only one speci c certi cate in the
trust store
ssl.certificate.trust-store-file-type
The trust store type. It is automatically detected based on the le
name or can be set manually.
ssl.certificate.trust-store-password
The password to open the trust store le.
ssl.cipher-suites
A list of strings of cipher suites to use. If not provided, a
reasonable default is selected.
ssl.protocols
The list of protocols to explicitly enable. (default: TLSv1.3 and
TLSv1.2).
Enables Server Name Indication (SNI), an TLS extension allowing
the server to use multiple certi cates. (default: false)
ssl.client-auth
Con gures the engine to require/request client authentication.
Possible values are: none, request and required. (default: none).
io-threads
The number if IO threads used to perform IO.
limits.max-header-size
The maximum length of all headers. (default: 20k)
limits.max-body-size
The maximum size of a request body. (default: 10M)
limits.max-chunk-size
The max HTTP chunk size.
limits.max-initial-line-length
The maximum length of the initial line. (default: 4096)
idle-timeout
Http connection idle timeout. (default: 30M)
enable-compression
If responses should be compressed.
read-timeout
Http connection read timeout for blocking IO. (default: 60s)
body.handle-file-uploads
If the les sent using multipart/form-data will be stored locally.
(default: true)
body.uploads-directory
The directory where the les sent using multipart/form-data
should be stored. (default: file-uploads)
body.merge-from-attributes
If the form attributes should be added to the request parameters.
(default: true)
body.delete-uploaded-files-on-end
If the uploaded les should be removed after serving the request.
body.preallocate-body-buffer
If the body buffer should pre-allocated based on the Content-
Length header value. (default: 1K)
auth.session.encryption-key
The encryption key that is used to store persistent logins.
so-reuse-port
Enable socket reuse port.
tcp-quick-ack
Enable tcp quick ack
tcp-cork
Enable tcp cork.
tcp-fast-open
Enable tcp fast open.
domain-socket
Path to a unix domain socket. (default:
/var/run/io.quarkus.app.socket)
domain-socket-enabled
Enables domain socket.
record-request-start-time
If enabled then start time will be recorded to enable logging of
total request time. (default: false)
access-log.enabled
If access logging is enabled. (default: false)
access-log.pattern
The access log pattern. (default: common)
access-log.log-to-file
If logging should be done to a separate le. (default: false)
access-log.base-file-name
The access log le base name. (default: quarkus)
access-log.log-directory
The log directory to use when logging access to a le.
access-log.log-directory
The log directory to use when logging access to a le.
access-log.log-suffix
The log le su x. (default: .log)
access-log.category
The log category to use if logging is being done via the standard
log mechanism. (default: io.quarkus.http.access-log)
access-log.rotate
If the log should be rotated daily. (default: true)
same-site-cookie.<name>.case-sensitive
If the cookie pattern is case sensitive.
same-site-cookie.<name>.value
The value to set in the samesite attribute.
same-site-cookie.<name>.enable-client-checker
Some User Agents break when sent SameSite=None, this will
detect them and avoid sending the value. (default: true)
same-site-cookie.<name>.add-secure-for-none
If this is true then the 'secure' attribute will automatically be sent
k h b f (d f l )
If metrics extension is registered, you can enable to get HTTP
metrics by setting quarkus.resteasy.metrics.enabled to true.
JAX-RS
Quarkus uses JAX-RS to de ne REST-ful web APIs. Under the
covers, Rest-EASY is working with Vert.X directly without using any
Servlet.
It is important to know that if you want to use any feature that
implies a Servlet (ie Servlet Filters) then you need to add the
quarkus-undertow extension to switch back to the Servlet
ecosystem but generally speaking, you don’t need to add it as
everything else is well-supported.
@Path("/book")
public class BookResource {
@GET
@Produces(MediaType.APPLICATION_JSON)
public List<Book> getAllBooks() {}
@POST
@Produces(MediaType.APPLICATION_JSON)
public Response createBook(Book book) {}
@DELETE
@Path("{isbn}")
@Produces(MediaType.APPLICATION_JSON)
public Response deleteBook(
@PathParam("isbn") String isbn) {}
@GET
@Produces(MediaType.APPLICATION_JSON)
@Path("search")
public Response searchBook(
@QueryParam("description") String description) {}
}
To get information from request:
@PathParam
Gets content from request URI. (example: /book/{id}
@PathParam("id"))
@QueryParam
Gets query parameter. (example: /book?desc=""
@QueryParam("desc))
@FormParam
Gets form parameter.
@MatrixParam
Get URI matrix parameter. (example:
/book;author=mkyong;country=malaysia)
@CookieParam
Gets cookie param by name.
@HeaderParam
Gets header parameter by name.
Valid HTTP method annotations provided by the spec are: @GET,
@POST, @PUT, @DELETE, @PATCH, @HEAD and @OPTIONS.
You can create new annotations that bind to HTTP methods not
de ned by the spec.
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@HttpMethod("LOCK")
public @interface LOCK {
}
@LOCK
public void lockIt() {}
}
Injecting
Using @Context annotation to inject JAX-RS and Servlet information.
@GET
public String getBase(@Context UriInfo uriInfo) {
return uriInfo.getBaseUri();
}
Possible injectable objects: SecurityContext, Request, Application,
Configuration, Providers, ResourceContext, ServletConfig,
ServletContext, HttpServletRequest, HttpServletResponse,
HttpHeaders, Urinfo, SseEventSink and Sse.
HTTP Filters
HTTP request and response can be intercepted to manipulate the
metadata (ie headers, parameters, media type, …) or abort a
request. You only need to implement the next
ContainerRequestFilter and ContainerResponseFilter JAX-RS
interfaces respectively.
@Provider
public class LoggingFilter
implements ContainerRequestFilter {
@Context
UriInfo info;
@Context
HttpServletRequest request;
@Override
public void filter(ContainerRequestContext context) {
final String method = context.getMethod();
final String path = info.getPath();
final String address = request.getRemoteAddr();
System.out.println("Request %s %s from IP %s",
method, path, address);
}
}
Exception Mapper
You can map exceptions to produce a custom output by
implementing ExceptionMapper interface:
@Provider
public class ErrorMapper
implements ExceptionMapper<Exception> {
@Override
public Response toResponse(Exception exception) {
int code = 500;
if (exception instanceof WebApplicationException) {
code = ((WebApplicationException) exception)
.getResponse().getStatus();
}
return Response.status(code)
.entity(
Json.createObjectBuilder()
.add("error", exception.getMessage())
.add("code", code)
.build()
)
.build();
}
}
Caching
Annotations to set Cache-Control headers:
@Produces(MediaType.APPLICATION_JSON)
@org.jboss.resteasy.annotations.cache.NoCache
public User me() {}
@Produces(MediaType.APPLICATION_JSON)
@org.jboss.resteasy.annotations.cache.Cache(
maxAge = 2000,
noStore = false
)
public User you() {}
Vert.X Filters and Routes
Programmatically
You can also register Vert.X Filters and Router programmatically
inside a CDI bean:
import io.quarkus.vertx.http.runtime.filters.Filters;
import io.vertx.ext.web.Router;
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.event.Observes;
@ApplicationScoped
public class MyBean {
public void filters(
@Observes Filters filters) {
filters
.register(
rc -> {
rc.response()
.putHeader("X-Filter", "filter 1");
rc.next();
},
10);
}
public void routes(
@Observes Router router) {
router
.get("/")
.handler(rc -> rc.response().end("OK"));
}
}
Declarative
You can use @Route annotation to use reactive routes and
@RouteFilter to sue reactive lters in a declarative way:
./mvnw quarkus:add-extension
-Dextensions="quarkus-vertx-web"
@ApplicationScoped
public class MyDeclarativeRoutes {
@Route(path = "/hello", methods = HttpMethod.GET)
public void greetings(RoutingContext rc) {
String name = rc.request().getParam("name");
if (name == null) {
name = "world";
}
rc.response().end("hello " + name);
}
@RouteFilter(20)
void filter(RoutingContext rc) {
rc.response().putHeader("X-Filter", "filter 2");
rc.next();
}
@Route
String hello(@Param Optional<String> name) {}
@Route
String helloFromHeader(@Header("My-Header") String head
er) {}
@Route
String createPerson(@Body Person person) {}
}
GraphQL
Quarkus integrates with GraphQL using MicroPro le GraphQL
integration.
./mvnw quarkus:add-extension
-Dextensions="graphql"
@GraphQLApi
public class FilmResource {
@Query("allFilms")
public List<String> films() {
}
@Query
public String getFilm(@Name("filmId") int id)) {}
@Query
public List<Hero> getHeroesWithSurname(
@DefaultValue("Skywalker") String surname) {
}
@Mutation
public Greetings load(Greetings greetings) {
}
}
If name not provided, then query name is resolved from method
name.
You can see the full schema at /graphql/schema.graphql. Also
GraphiQL UI is enabled at dev and test mode at /graphql-ui/.
Extension can be con gured with the follwoing paramters pre xed
with quarkus.smallrye-graphql.
root-path
The rootPath under which queries will be served. (default:
/graphql)
root-path-ui
The path where GraphQL UI is available. (default: /graphql-ui)
always-include-ui
The path where GraphQL UI is available. (default: /graphql-ui)
root-path-ui
Always include the UI. By default this will only be included in dev
and test. (default: false)
enable-ui
If GraphQL UI should be enabled. (default: false)
schema-available
Make the schema available over HTTP. (default: true)
metrics.enabled
Enable metrics. (default: false)
GraphQL Clients
./mvnw quarkus:add-extension
-Dextensions="graphql-client"
quarkus.smallrye-graphql-client.star-wars.url=https://swapi
-graphql.netlify.app/.netlify/functions/index
Typesafe client
@GraphQLClientApi(configKey = "star-wars")
public interface StarWarsClientApi {
FilmConnection allFilms();
}
@Inject
StarWarsClientApi typesafeClient;
allFilms is also the name of the query. You can override the value
using @Query(value="allStarWarsFilms")
Dynamic client
@Inject
@GraphQLClient("star-wars")
DynamicGraphQLClient dynamicClient;
Document query = document(
operation(
field("allFilms",
field("films",
field("title"),
field("planetConnection",
field("planets",
field("name")
)
)
)
)
)
);
Response response = dynamicClient.executeSync(query)
Vert.X Verticle
Vert.X Verticles are also supported:
@ApplicationScoped
public class VerticleDeployer {
@Inject
Vertx vertx;
public void init(@Observes StartupEvent ev) {
CountDownLatch latch = new CountDownLatch(1);
vertx.deployVerticle(BareVerticle::new,
new DeploymentOptions()
.setConfig(
new JsonObject()
.put("id", "bare")
)
)
.thenAccept(x -> latch.countDown());
latch.countDown();
}
}
Verticles can be:
bare
extending io.vertx.core.AbstractVerticle.
mutiny
extendig io.smallrye.mutiny.vertx.core.AbstractVerticle.
GZip Support
You can con gure Quarkus to use GZip in the
application.properties le using the next properties with
quarkus.resteasy su x:
gzip.enabled
EnableGZip. (default: false)
gzip.max-input
Con gure the upper limit on de ated request body. (default: 10M)
GRPC
Quarkus integrates with gRPC:
./mvnw quarkus:add-extension
-Dextensions="quarkus-grpc"
Then you need to con gure build tool with gRPC plugins. In the
case of Maven, the kr.motd.maven:os-maven-plugin extension and
org.xolstice.maven.plugins:protobuf-maven-plugin
Protos les are stored at src/main/proto.
When java les are created two service implementations are
provided: one with default gRPC API and other with Mutiny support.
With quarkus.grpc.server pre x, the next con guration properties
can be set:
port
The gRPC Server port. (default: 9000)
host
The gRPC server host. (default: 0.0.0.0)
handshake-timeout
The gRPC handshake timeout.
max-inbound-message-size
The max inbound message size in bytes.
plain-text
Use plain text. (default: true)
alpn
TWhether ALPN should be used. (default: true)
enable-reflection-service
Enables the gRPC Re ection Service. (default: false)
ssl.certificate
The le path to a server certi cate or certi cate chain in PEM
format.
ssl.key
The le path to the corresponding certi cate private key le in
PEM format.
ssl.key-store
An optional key store which holds the certi cate information
instead of specifying separate les.
ssl.key-store-type
An optional parameter to specify the type of the key store le.
ssl.key-store-password
A parameter to specify the password of the key store le.
(default: password)
ssl.trust-store
Trust store which holds the certi cate information of the
certi cates to trust
ssl.trust-store-type
Parameter to specify type of the trust store le.
ssl.trust-store-password
A parameter to specify the password of the trust store le.
ssl.cipher-suites
A list of the cipher suites to use.
ssl.protocols
The list of protocols to explicitly enable. (default:
TLSv1.3,TLSv1.2)
transport-security.certificate
The path to the certi cate le.
transport-security.key
The path to the private key le.
load-balancing-policy
Use a custom load balancing policy. Possible values: pick_first,
round_robin, grpclb. (default: pick_first)
To consume the service:
@GrpcClient("hello")
GreeterGrpc.GreeterBlockingStub client;
@GrpcClient("hello")
io.grpc.Channel channel;
// Adding headers
Metadata extraHeaders = new Metadata();
extraHeaders.put("my-header", "my-interface-value");
GreeterBlockingStub alteredClient = io.quarkus.grpc.GrpcCli
entUtils.attachHeaders(client, extraHeaders);
Interceptors
import io.quarkus.grpc.GlobalInterceptor;
import io.grpc.ClientInterceptor;
@GlobalInterceptor
@ApplicationScoped
public class MyInterceptor implements ClientInterceptor {}
@RegisterClientInterceptor(MySpecialInterceptor.class) (1)
@GrpcClient("helloService")
Greeter greeter;
Some con guration example to set the host and the SSL
parameters:
quarkus.grpc.clients.hello.host=localhost
quarkus.grpc.clients.hello.plain-text=false
quarkus.grpc.clients.hello.ssl.certificate=src/main/resourc
es/tls/client.pem
quarkus.grpc.clients.hello.ssl.key=src/main/resources/tls/c
lient.key
quarkus.grpc.clients.hello.ssl.trust-store=src/main/resourc
es/tls/ca.pem
Smallrye Stork
Stork implements client load-balancing strategies supporting
Kubernetes, and Consul.
Consul
Add following dependencies:
<dependency>
<groupId>io.smallrye.stork</groupId>
<artifactId>stork-service-discovery-consul</artifactId>
</dependency>
<dependency>
<groupId>io.smallrye.reactive</groupId>
<artifactId>smallrye-mutiny-vertx-consul-client</artifact
Id>
</dependency>
Register service instances to Consul:
@ApplicationScoped
public class Registration {
@ConfigProperty(name = "consul.host") String host;
@ConfigProperty(name = "consul.port") int port;
public void init(@Observes StartupEvent ev, Vertx vert
x) {
ConsulClient client = ConsulClient.create(vertx,
new ConsulClientOptions().s
etHost(host).setPort(port));
client.registerServiceAndAwait(
new ServiceOptions().setPort(8080)
.setAddress("host1").setName("my-servic
e").setId("blue"));
client.registerServiceAndAwait(
new ServiceOptions().setPort(8080)
.setAddress("host2").setName("my-servic
e").setId("red"));
}
}
Con guration:
consul.host=localhost
consul.port=8500
stork.my-service.service-discovery=consul
stork.my-service.service-discovery.consul-host=localhost
stork.my-service.service-discovery.consul-port=8500
stork.my-service.load-balancer=round-robin
Kubernetes
Add following dependencies:
<dependency>
<groupId>io.smallrye.reactive</groupId>
<artifactId>stork-service-discovery-kubernetes</artifactI
d>
</dependency>
stork.my-service.service-discovery=kubernetes
stork.my-service.service-discovery.k8s-namespace=my-namespa
ce
stork.my-service.load-balancer=round-robin
Using Stork at client
@RegisterRestClient(baseUri = "stork://my-service")
public interface MyService {
@GET
@Produces(MediaType.TEXT_PLAIN)
String get();
}
Fault Tolerance
Quarkus uses MicroPro le Fault Tolerance spec:
./mvnw quarkus:add-extension
-Dextensions="io.quarkus:quarkus-smallrye-fault-toleranc
e"
MicroPro le Fault Tolerance spec uses CDI interceptor and it can
be used in several elements such as CDI bean, JAX-RS resource or
MicroPro le Rest Client.
To do automatic retries on a method:
@Path("/api")
@RegisterRestClient
public interface WorldClockService {
@GET @Path("/json/cet/now")
@Produces(MediaType.APPLICATION_JSON)
@Retry(maxRetries = 2)
WorldClock getNow();
}
You can set fallback code in case of an error by using @Fallback
annotation:
@Retry(maxRetries = 1)
@Fallback(fallbackMethod = "fallbackMethod")
WorldClock getNow(){}
public WorldClock fallbackMethod() {
return new WorldClock();
}
fallbackMethod must have the same parameters and return type as
the annotated method.
You can also set logic into a class that implements FallbackHandler
interface:
public class RecoverFallback
implements FallbackHandler<WorldClock> {
@Override
public WorldClock handle(ExecutionContext context) {
}
}
And set it in the annotation as value
@Fallback(RecoverFallback.class).
In case you want to use circuit breaker pattern:
@CircuitBreaker(requestVolumeThreshold = 4,
failureRatio=0.75,
delay = 1000)
WorldClock getNow(){}
If 3 (4 x 0.75) failures occur among the rolling window of 4
consecutive invocations then the circuit is opened for 1000 ms and
then be back to half open. If the invocation succeeds then the
circuit is back to closed again.
You can use bulkahead pattern to limit the number of concurrent
access to the same resource. If the operation is synchronous it
uses a semaphore approach, if it is asynchronous a thread-pool
one. When a request cannot be processed BulkheadException is
thrown. It can be used together with any other fault tolerance
annotation.
@Bulkhead(5)
@Retry(maxRetries = 4,
delay = 1000,
retryOn = BulkheadException.class)
WorldClock getNow(){}
From smallrye project Fibonacci and Exponential Backoff retries
annotations are provided:
public class TwoBackoffsOnMethodService {
@Retry
@io.smallrye.faulttolerance.api.ExponentialBackoff
@io.smallrye.faulttolerance.api.FibonacciBackoff
public void hello() {
throw new IllegalArgumentException();
}
}
Fault tolerance annotations:
Annotation Properties
@Timeout unit
@Retry
maxRetries, delay, delayUnit,
maxDuration, durationUnit,
jitter, jitterDelayUnit, retryOn,
abortOn
@Fallback fallbackMethod
@Bulkhead
waitingTaskQueue (only valid in
asynchronous)
Annotation Properties
@CircuitBreaker
failOn, delay, delayUnit,
requestVolumeThreshold,
failureRatio, successThreshold
@Asynchronous
You can override annotation parameters via con guration le using
property [classname/methodname/]annotation/parameter:
org.acme.quickstart.WorldClock/getNow/Retry/maxDuration=30
# Class scope
org.acme.quickstart.WorldClock/Retry/maxDuration=3000
# Global
Retry/maxDuration=3000
You can also enable/disable policies using special parameter
enabled.
org.acme.quickstart.WorldClock/getNow/Retry/enabled=false
# Disable everything except fallback
MP_Fault_Tolerance_NonFallback_Enabled=false
MicroPro le Fault Tolerance integrates with MicroPro le
Metrics spec. You can disable it by setting
MP_Fault_Tolerance_Metrics_Enabled to false.
Observability
Health Checks
Quarkus relies on MicroPro le Health spec to provide health
checks.
./mvnw quarkus:add-extension
-Dextensions="io.quarkus:quarkus-smallrye-health"
By just adding this extension, an endpoint is registered to /q/health
providing a default health check.
{
"status": "UP",
"checks": [
]
}
To create a custom health check you need to implement the
HealthCheck interface and annotate either with @Readiness (ready to
process requests) or @Liveness (is running) annotations.
@Readiness
public class DatabaseHealthCheck implements HealthCheck {
@Override
public HealthCheckResponse call() {
HealthCheckResponseBuilder responseBuilder =
HealthCheckResponse.named("Database conn");
try {
checkDatabaseConnection();
responseBuilder.withData("connection", true);
responseBuilder.up();
} catch (IOException e) {
// cannot access the database
responseBuilder.down()
.withData("error", e.getMessage());
}
return responseBuilder.build();
}
}
Builds the next output:
{
"status": "UP",
"checks": [
{
"name": "Database conn",
"status": "UP",
"data": {
"connection": true
}
}
]
}
Since health checks are CDI beans, you can do:
@ApplicationScoped
public class DatabaseHealthCheck {
@Liveness
HealthCheck check1() {
return io.smallrye.health.HealthStatus
.up("successful-live");
}
@Readiness
HealthCheck check2() {
return HealthStatus
.state("successful-read", this::isReady)
}
private boolean isReady() {}
}
You can ping liveness or readiness health checks individually by
querying /q/health/live or /q/health/ready.
Quarkus comes with some HealthCheck implementations for
checking service status.
SocketHealthCheck: checks if host is reachable using a
socket.
UrlHealthCheck: checks if host is reachable using a Http URL
connection.
InetAddressHealthCheck: checks if host is reachable using
InetAddress.isReachable method.
@Liveness
HealthCheck check1() {
return new UrlHealthCheck("https://www.google.com")
.name("Google-Check");
}
If you want to override or set manually readiness/liveness probes,
you can do it by setting health properties:
quarkus.smallrye-health.root-path=/hello
quarkus.smallrye-health.liveness-path=/customlive
quarkus.smallrye-health.readiness-path=/customready
Automatic readiness probes
Some default readiness probes are provided by default if any of the
next features are added:
datasource
A probe to check database connection status.
kafka
A probe to check kafka connection status. In this case you need
to enable manually by setting quarkus.kafka.health.enabled to
true.
mongoDB
A probe to check MongoDB connection status.
neo4j
A probe to check Neo4J connection status.
artemis
A probe to check Artemis JMS connection status.
kafka-streams
Liveness (for stream state) and Readiness (topics created)
probes.
vault
A probe to check Vault conection status.
gRPC
A readiness probe for the gRPC services.
Cassandra
A readiness probe to check Cassandra connection status.
Redis
A readiness probe to check Redis connection status.
You can disable the automatic generation by setting
<component>.health.enabled to false.
quarkus.datasource.myotherdatasource.health-exclude=true
quarkus.datasource.health.enabled=true
quarkus.kafka-streams.health.enabled=false
quarkus.mongodb.health.enabled=false
quarkus.neo4j.health.enabled=false
In the case of Vault you can pass parameters to modify the call of
the status endpoint in Vault.
quarkus.vault.health.enabled=true
quarkus.vault.health.stand-by-ok=true
quarkus.vault.health.performance-stand-by-ok=true
Health groups are supported to provide custom health checks
groups:
@io.smallrye.health.HealthGroup("mygroup1")
public class SimpleHealthGroupCheck implements HealthCheck
{
}
You can ping grouped health checks by querying /group/mygroup1.
Group root path can be con gured:
quarkus.smallrye-health.group-path=/customgroup
MicroPro le Health currently doesn’t support returning reactive
types, but SmallRye Health does. Implement the
io.smallrye.health.api.AsyncHealthCheck interface instead of the
org.eclipse.microprofile.health.HealthCheck.
@Liveness
@ApplicationScoped
public class LivenessAsync implements AsyncHealthCheck {
@Override
public Uni<HealthCheckResponse> call() {
return Uni.createFrom().item(HealthCheckResponse.up
("liveness-reactive"))
.onItem().delayIt().by(Duration.ofMillis(10
));
}
}
Metrics
Quarkus can utilize the MicroPro le Metrics spec to provide metrics
support.
./mvnw quarkus:add-extension
-Dextensions="io.quarkus:quarkus-smallrye-metrics"
The metrics can be read with JSON or the OpenMetrics format. An
endpoint is registered automatically at /q/metrics providing default
metrics.
MicroPro le Metrics annotations:
@Timed
Tracks the duration.
@SimplyTimed
Tracks the duration without mean and distribution calculations.
@Metered
Tracks the frequency of invocations.
@Counted
Counts number of invocations.
@Gauge
Samples the value of the annotated object.
@ConcurrentGauge
Gauge to count parallel invocations.
@Metric
Used to inject a metric. Valid types Meter, Timer, Counter,
Histogram. Gauge only on producer methods/ elds.
@GET
//...
@Timed(name = "checksTimer",
description = "A measure of how long it takes
to perform a hello.",
unit = MetricUnits.MILLISECONDS)
public String hello() {}
@Counted(name = "countWelcome",
description = "How many welcome have been performed.")
public String hello() {}
@Gauge annotation returning a measure as a gauge.
@Gauge(name = "hottestSauce", unit = MetricUnits.NONE,
description = "Hottest Sauce so far.")
public Long hottestSauce() {}
Injecting a histogram using @Metric.
@Inject
@Metric(name = "histogram")
Histogram historgram;
You can con gure Metrics:
quarkus.smallrye-metrics.path=/mymetrics
Pre x is quarkus.smallrye-metrics.
path
The path to the metrics handler. (default: /q/metrics)
extensions.enabled
Metrics are enabled or not. (default: true)
micrometer.compatibility
Apply Micrometer compatibility mode. (default: false)
quarkus.hibernate-orm.metrics.enabled set to true exposes
Hibernate metrics under vendor scope.
quarkus.mongodb.metrics.enabled set to true exposes MongoDB
metrics under vendor scope.
You can apply metrics annotations via CDI stereotypes:
@Stereotype
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE, ElementType.METHOD, ElementTyp
e.FIELD })
@Timed(name = "checksTimer",
description = "A measure of how long it takes
to perform a hello.",
unit = MetricUnits.MILLISECONDS)
public @interface TimedMilliseconds {
}
There is a tight integration with Micrometer in the form of an
extension:
./mvnw quarkus:add-extension
-Dextensions="micrometer"
Add a micrometer dependency for the registry of your choosing:
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
</dependency>
You can con gure Micrometer. Pre x is quarkus.micrometer:
enabled
Micrometer metrics support. (default: true)
registry-enabled-default
Micrometer MeterRegistry discovery. (default: true)
binder-enabled-default
Micrometer MeterBinder discovery. (default: true)
binder.vertx.enabled
Vert.x metrics support.
binder.mp-metrics.enabled
Micropro le Metrics support.
binder.jvm
Micrometer JVM metrics support. (default: true)
binder.system
Micrometer System metrics support. (default: true)
export.datadog.enabled
Support for export to Datadog Support for Datadog.
export.jmx.enabled
Support for export to JMX Support for JMX.
export.prometheus.enabled
Support for export to Prometheus.
export.prometheus.path
The path for the prometheus metrics endpoint (produces
text/plain). (default: /q/metrics)
export.azuremonitor.enabled
Support for export to Azure Monitor.
export.azuremonitor.instrumentation-key
The path for the azure monitor instrumentationKey.
export.statsd.enabled
Support for export to StatsD.
export.stackdriver.enabled
Micrometer metrics support. (default: true)
export.signalfx.enabled
Micrometer metrics support. (default: true)
export.signalfx.uri
Signalfx URI.
export.signalfx.access-token
Access Token.
binder.vertx.match-patterns
Comma-separated case-sensitive list of regular expressions
de ning Paths that should be matched and used as tags
binder.vertx.ignore-patterns
Comma-separated case-sensitive list of regular expressions
de ning Paths that should be ignored / not measured.
export.datadog
Datadog MeterRegistry con guration in Map<String, String>
format.
export.jmx
JMX registry con guration properties in Map<String, String>
format.
export.prometheus
Prometheus registry con guration properties in Map<String,
String> format.
export.stackdriver
Stackdriver registry con guration properties in Map<String,
String> format.
Tracing
Quarkus can utilize the MicroPro le OpenTracing spec.
./mvnw quarkus:add-extension
-Dextensions="io.quarkus:quarkus-smallrye-opentracing"
Requests sent to any endpoint are traced automatically.
This extension includes OpenTracing support and Jaeger tracer.
Jaeger tracer con guration:
quarkus.jaeger.service-name=myservice
quarkus.jaeger.sampler-type=const
quarkus.jaeger.sampler-param=1
quarkus.jaeger.endpoint=http://localhost:14268/api/traces
quarkus.jaeger.metrics.enabled=true
@Traced annotation can be set to disable tracing at class or method
level.
Tracer class can be injected into the class.
@Inject
Tracer tracer;
tracer.activeSpan().setBaggageItem("key", "value");
You can disable Jaeger extension by using quarkus.jaeger.enabled
property.
You can log the traceId, spanId and sampled in normal log:
quarkus.log.console.format=%d{HH:mm:ss} %-5p traceId=%X{tra
ceId},
spanId=%X{spanId}, sampled
=%X{sampled} [%c{2.}] (%t) %s%e%n
Additional tracers
JDBC Tracer
Adds a span for each JDBC queries.
<dependency>
<groupId>io.opentracing.contrib</groupId>
<artifactId>opentracing-jdbc</artifactId>
</dependency>
Con gure JDBC driver apart from tracing properties seen before:
# add ':tracing' to your database URL
quarkus.datasource.url=
jdbc:tracing:postgresql://localhost:5432/mydatabase
quarkus.datasource.driver=
io.opentracing.contrib.jdbc.TracingDriver
quarkus.hibernate-orm.dialect=
org.hibernate.dialect.PostgreSQLDialect
OpenTelemetry
./mvnw quarkus:add-extension
-Dextensions="opentelemetry-otlp-exporter"
Possible con guration:
quarkus.application.name=myservice
quarkus.opentelemetry.enabled=true
quarkus.opentelemetry.tracer.exporter.otlp.endpoint=http://
localhost:4317
quarkus.opentelemetry.tracer.exporter.otlp.headers=Authoriz
ation=Bearer my_secret
The OpenTelemetry extension enables the W3C Trace Context and
the W3C Baggage propagators, you can however choose any of the
supported OpenTelemetry propagators.
The b3, b3multi, jaeger and ottrace propagators:
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-extension-trace-propagators</
artifactId>
</dependency>
The propagator:
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-extension-aws</artifactId>
</dependency>
You can con gure OpenTelemetry. Pre x is quarkus.opentelemetry:
enabled
OpenTelemetry support (default: true)
propagators
Comma separated list of OpenTelemetry propagators which must
be supported. Possible values b3, b3multi, baggage, jaeger,
ottrace, tracecontext, xray (default: traceContext,baggage).
tracer.enabled
Support for tracing with OpenTelemetry.
tracer.resource-attributes
A comma separated list of name=value resource attributes that
represents the entity producing telemetry
tracer.sampler
The sampler to use for tracing. Possible values off, on, ratio.
(Default: on)
tracer.sampler.ratio
Ratio to sample
tracer.sampler.parent-based
If the sampler to use for tracing is parent based (default: true)
tracer.suppress-non-application-uris
Suppress non-application uris from trace collection. (default:
true)
tracer.exporter.otlp.enabled
OTLP SpanExporter support (default: true)
tracer.exporter.otlp.endpoint
The OTLP endpoint to connect to
tracer.exporter.otlp.headers
Key-value pairs to be used as headers associated with gRPC
requests
tracer.exporter.otlp.export-timeout
The maximum amount of time to wait for the collector to process
exported spans before an exception is thrown. (default: 10S)
tracer.exporter.otlp.compression
Compression method to be used by exporter to compress the
payload
Kafka Tracer
Adds a span for each message sent to or received from a Kafka
t i
<dependency>
<groupId>io.opentracing.contrib</groupId>
<artifactId>opentracing-kafka-client<</artifactId>
</dependency>
And con gure it:
...
mp.messaging.outgoing.generated-price.topic=prices
# For Produces
mp.messaging.outgoing.generated-price.interceptor.classes=i
o.opentracing.contrib.kafka.TracingProducerInterceptor
...
# For consumers
mp.messaging.incoming.prices.interceptor.classes=io.opentra
cing.contrib.kafka.TracingConsumerInterceptor
AWS XRay
If you are building native images, and want to use AWS X-Ray
Tracing with your lambda you will need to include quarkus-amazon-
lambda-xray as a dependency in your pom.
Native Executable
You can build a native image by using GraalVM. The common use
case is creating a Docker image so you can execute the next
commands:
./mvnw package -Pnative -Dquarkus.native.container-build=tr
ue
docker build -f src/main/docker/Dockerfile.native
-t quarkus/getting-started .
docker run -i --rm -p 8080:8080 quarkus/getting-started
You can use quarkus.native.container-runtime to select the
container runtime to use. Now docker (default) and podman are the
valid options.
./mvnw package -Pnative -Dquarkus.native.container-runtime=
podman
To con gure native application, you can create a config directory at
the same place as the native le and place an
application.properties le inside. config/application.properties.
To produce a native executable with native excutable use -
Dquarkus.native.additional-build-args=-J—enable-preview.
SSL
To create a native image with SSL you need to copy SunEC library
and certi cates:
Java 8:
FROM quay.io/quarkus/ubi-quarkus-native-image:{graalvm-vers
ion}-java8 as nativebuilder
RUN mkdir -p /tmp/ssl-libs/lib 
&& cp /opt/graalvm/jre/lib/security/cacerts /tmp/ssl-libs

&& cp /opt/graalvm/jre/lib/amd64/libsunec.so /tmp/ssl-lib
s/lib/
FROM registry.access.redhat.com/ubi8/ubi-minimal
WORKDIR /work/
COPY --from=nativebuilder /tmp/ssl-libs/ /work/
COPY target/*-runner /work/application
RUN chmod 775 /work /work/application
EXPOSE 8080
CMD ["./application", "-Dquarkus.http.host=0.0.0.0", "-Djav
a.library.path=/work/lib", "-Djavax.net.ssl.trustStore=/wor
k/cacerts"]
Java 11:
FROM quay.io/quarkus/ubi-quarkus-native-image:{graalvm-vers
ion}-java11 as nativebuilder
RUN mkdir -p /tmp/ssl-libs/lib 
&& cp /opt/graalvm/lib/security/cacerts /tmp/ssl-libs 
&& cp /opt/graalvm/lib/libsunec.so /tmp/ssl-libs/lib/
FROM registry.access.redhat.com/ubi8/ubi-minimal
WORKDIR /work/
COPY --from=nativebuilder /tmp/ssl-libs/ /work/
COPY target/*-runner /work/application
RUN chmod 775 /work /work/application
EXPOSE 8080
CMD ["./application", "-Dquarkus.http.host=0.0.0.0", "-Djav
a.library.path=/work/lib", "-Djavax.net.ssl.trustStore=/wor
k/cacerts"]
Inclusion of resources
By default, no resources are included in native executable.
quarkus.native.resources.includes allows to set glob expressions to
include resources based on src/main/resources path.
Given src/main/resources/foo/selected.png:
quarkus.native.resources.includes=foo/**
Exclusion of resources
By default, no resources are excluded.
quarkus.native.resources.excludes = foo/**
Native con guration properties pre xed with quarkus.native:
additional-build-args
Additional arguments to pass to the build process.
enable-http-url-handler
If the HTTP url handler should be enabled. (default: true)
enable-https-url-handler
If the HTTPS url handler should be enabled.
enable-all-security-services
If all security services should be added to the native image.
user-language
De nes the user language used for building the native
executable.
user-country
De nes the user country used for building the native executable.
file-encoding
De nes the le encoding.
If all character sets should be added to the native image.
graalvm-home
The location of the Graal distribution.
java-home
The location of the JDK.
native-image-xmx
The maximum Java heap to be used during the native image
generation.
debug-build-process
If the native image build should wait for a debugger to be
attached before running.
publish-debug-build-process-port
If the debug port should be published when building with docker
and debug-build-process. (default: true)
cleanup-server
If the native image server should be restarted.
enable-isolates
If isolates should be enabled. (default: true)
enable-fallback-images
If a JVM based 'fallback image' should be created if native image
fails.
enable-server
If the native image server should be used.
auto-service-loader-registration
If all META-INF/services entries should be automatically
registered.
dump-proxies
If the bytecode of all proxies should be dumped for inspection.
container-build
If this build should be done using a container runtime.
remote-container-build
If this build is done using a remote docker daemon.
builder-image
The docker image to use to do the image build.
container-runtime
The container runtime that is used to do an image based build.
(docker, podman)
container-runtime-options
Options to pass to the container runtime.
enable-vm-inspection
If the resulting image should allow VM introspection
full-stack-traces
If full stack traces are enabled in the resulting image.
enable-reports
If the reports on call paths and included
packages/classes/methods should be generated.
report-exception-stack-traces
If exceptions should be reported with a full stack trace.
report-errors-at-runtime
If errors should be reported at runtime.
enable-dashboard-dump
Generate the report les for GraalVM Dashboard.
resources.includes
A comma separated list of globs to match resource paths that
should be added to the native image.
resources.excludes
A comma separated list of globs to match resource paths that
should exclude to the native image.
debug.enabled
If debug is enabled and debug symbols are generated.
Container Images Creation
You can levarage to Quarkus to generation and release of Docker
containers. It provides several extensions to make it so.
mvn clean package
-Dquarkus.container-image.build=true
-Dquarkus.container-image.push=true
-Dquarkus.container-image.registry=quay.io
Pre x is quarkus.container-image:
group
The group/repository of the image. (default: the ${user.name})
name
The name of the image. (default: the application name)
tag
The tag of the image. (default: the application version)
additional-tags
Additional tags of the container image.
registry
The registry to use for pushing. (default: docker.io)
username
The registry username.
password
The registry password.
insecure
Flag to allow insecure registries. (default: false)
build
Boolean to set if image should be built. (default: false)
push
Boolean to set if image should be pushed. (default: false)
labels
Custom labels to add to the generated image.
Jib
./mvnw quarkus:add-extensions
-Dextensions="quarkus-container-image-jib"
Quarkus copies any le under src/main/jib into the built container
image.
Pre x is quarkus.container-image-jib:
base-jvm-image
The base image to use for the jib build. (default: fabric8/java-
alpine-openjdk8-jre)
base-native-image
The base image to use for the native build. (default:
registry.access.redhat.com/ubi8/ubi-minimal)
jvm-arguments
The arguments to pass to java. (default: -
Dquarkus.http.host=0.0.0.0,-
Djava.util.logging.manager=org.jboss.logmanager.LogManager)
native-arguments
The arguments to pass to the native application. (default: -
Dquarkus.http.host=0.0.0.0)
environment-variables
Map of environment variables.
jvm-entrypoint
A custom entry point of the container image in JVM mode.
native-entrypoint
A custom entry point of the container image in native mode.
offline-mode
Whether or not to operate o ine. (default: false)
base-registry-username
The username to use to authenticate with the registry used to
pull the base JVM image.
base-registry-password
The password to use to authenticate with the registry used to pull
the base JVM image.
ports
The ports to expose.
user
The user to use in generated image.
always-cache-base-image
Controls the optimization which skips downloading base image
layers that exist in a target registry (default: false).
appcds-builder-image
When AppCDS generation is enabled, if this property is set, then
the JVM used to generate the AppCDS le will be the JVM
present in the container image.
platforms
List of target platforms. (ie linux/amd64).
docker-executable-ame
Name of binary used to execute the docker commands.
Docker
./mvnw quarkus:add-extensions
-Dextensions="quarkus-container-image-docker"
Pre x is quarkus.container-image-s2i:
dockerfile-jvm-path
Path to the JVM Docker le. (default:
${project.root}/src/main/docker/Dockerfile.jvm)
dockerfile-native-path
Path to the native Docker le. (default:
${project.root}/src/main/docker/Dockerfile.native)
Buildpacks
./mvnw quarkus:add-extensions
-Dextensions="quarkus-container-image-buildpack"
Pre x is quarkus.buildpack:
jvm-builder-image
The buildpacks builder image to use when building the project in
jvm mode.
native-builder-image
The buildpacks builder image to use when building the project in
native mode.
builder-env
Environment key/values to pass to buildpacks.
run-image
The buildpacks run image to use when building the project.
pull-timeout-seconds
Max pull timeout for builder/run images, in seconds (default:
300)
docker-host
DOCKER_HOST value to use.
log-level
Log level to use. (default info)
base-registry-username
The username to use to authenticate with the registry used to
pull the base image.
base-registry-password
The password to use to authenticate with the registry used to pull
the base image.
S2I
./mvnw quarkus:add-extensions
-Dextensions="quarkus-container-image-s2i"
Pre x is quarkus.container-image-docker:
base-jvm-image
The base image to use for the s2i build. (default: fabric8/java-
alpine-openjdk8-jre)
base-native-image
The base image to use for the native build. (default:
registry.access.redhat.com/ubi8/ubi-minimal)
Kubernetes
Quarkus can use Dekorate to generate Kubernetes resources.
./mvnw quarkus:add-extensions
-Dextensions="quarkus-kubernetes"
Running ./mvnw package the Kubernetes resources are created at
target/kubernetes/ directory.
Container Images Creation integrates with Kubernetes
extension, so no need of extra Kubernetes properties.
Generated resource is integrated with MicroPro le Health
annotations.
Also, you can customize the generated resource by setting the new
values in application.properties:
quarkus.kubernetes.namespace=mynamespace
quarkus.kubernetes.replicas=3
quarkus.kubernetes.labels.foo=bar
quarkus.kubernetes.readiness-probe.period-seconds=45
quarkus.kubernetes.mounts.github-token.path=/deployment/git
hub
quarkus.kubernetes.mounts.github-token.read-only=true
quarkus.kubernetes.secret-volumes.github-token.volume-name=
github-token
quarkus.kubernetes.secret-volumes.github-token.secret-name=
greeting-security
quarkus.kubernetes.secret-volumes.github-token.default-mode
=420
quarkus.kubernetes.config-map-volumes.github-token.config-m
ap-name=my-secret
quarkus.kubernetes.expose=true
quarkus.kubernetes.ingress.expose=true
quarkus.kubernetes.ingress.host=example.com
quarkus.kubernetes.env.vars.my-env-var=foobar
quarkus.kubernetes.env.configmaps=my-config-map,another-con
fig-map
quarkus.kubernetes.env.secrets=my-secret,my-other-secret
quarkus.kubernetes.resources.requests.memory=64Mi
quarkus.kubernetes.resources.requests.cpu=250m
quarkus.kubernetes.resources.limits.memory=512Mi
quarkus.kubernetes.resources.limits.cpu=1000m
All possible values are explained at
https://quarkus.io/guides/kubernetes#con guration-options.
Labels and Annotations
The generated manifest use the Kubernetes recommended labels
and annotations.
"labels" : {
"app.kubernetes.io/part-of" : "todo-app",
"app.kubernetes.io/name" : "todo-rest",
"app.kubernetes.io/version" : "1.0-rc.1"
}
"annotations": {
"app.quarkus.io/vcs-url" : "<some url>",
"app.quarkus.io/commit-id" : "<some git SHA>",
}
You can override the labels by using the next properties:
quarkus.kubernetes.part-of=todo-app
quarkus.kubernetes.name=todo-rest
quarkus.kubernetes.version=1.0-rc.1
Or add new labels and/or annotations:
quarkus.kubernetes.labels.foo=bar
quarkus.kubernetes.annotations.foo=bar
metrics
When using metrics extension, Prometheus annotations are
generated:
prometheus.io/scrape: "true"
prometheus.io/path: /metrics
prometheus.io/port: "8080"
Kubernetes Deployment Targets
You can generate different resources setting the property
quarkus.kubernetes.deployment-target.
Possible values are kubernetes, openshift and knative. The default
value is kubernetes.
Knative Properties
Most of the Kubernetes properties are valid in Knative output by
just changing the kubernetes pre x to knative pre x (ie
quarkus.kubernetes.readiness-probe.period-seconds to
quarkus.knative.readiness-probe.period-seconds).
There are also speci c properties for Knative:
quarkus.kubernetes.deployment-target=knative
quarkus.knative.revision-name=my-revision
quarkus.knative.traffic.my-revision.percentage=80
List of con guration options:
kubernetes
https://quarkus.io/guides/kubernetes#con guration-options
openshift
https://quarkus.io/guides/kubernetes#openshift
Knative
https://quarkus.io/guides/kubernetes#knative
Using Existing Resources
You an provide your Kubernetes resources in form of yaml/json and
they will provide additional resources or be used as base for the
generation process:
Resources are added in src/main/kubernetes directory with the
target name (kubernetes.json, openshift.json, knative.json, or the
yml equivalents) with one orm ore Kubernetes resources. Any
resource found will be added in the generated manifests. If one of
the provided resources has the same name as one of the generated
ones, then the generated resource will be created on top of the
provided resource, respecting existing content.
To override the name of the generated resource you can use:
quarkus.kubernetes.name, quarkus.openshift.name and
quarkus.knative.name.
Deployment
To deploy automatically the generated resources, you need to set
quarkus.container.deploy ag to true.
mvn clean package -Dquarkus.kubernetes.deploy=true
If you set this ag to true, the build and push ags from
container-image are set to true too.
To deploy the application, the extension uses the
https://github.com/fabric8io/kubernetes-client. All options
described at Kubernetes Client are valid here.
Kubernetes Service Binding
Quarkus supports binding services to applications via the Service
Binding Speci cation for Kubernetes.
The following Quarkus extensions support this feature:
quarkus-jdbc-mariadb
quarkus-jdbc-mssql
quarkus-jdbc-mysql
quarkus-jdbc-postgresql
quarkus-kafka-client
quarkus-smallrye-reactive-messaging-kafka
quarkus-mongodb
./mvnw quarkus:add-extensions
-Dextensions="quarkus-kubernetes-service-binding"
Datasource con guration part is absent as it is auto-discovered by
Quarkus.
Minikube
Quarkus has a Minikube extension which creates Kubernetes
manifests that are tailored for Minikube.
./mvnw quarkus:add-extension
-Dextensions="minikube"
Remember to execute eval $(minikube -p minikube docker-
env) to build images directly inside Minkube cluster.
OpenShift
Instead of adding Kubernetes extension, set container image s2i
and the target to openshift for working with OpenShift, an
extension grouping all of the is created:
./mvnw quarkus:add-extension
-Dextensions="openshift"
Kubernetes Con guration Extension
Integration between MicroPro le Con g spec and Con gMaps &
Secrets:
./mvnw quarkus:add-extensions
-Dextensions="quarkus-kubernetes-config"
quarkus.kubernetes-config.enabled=true
quarkus.kubernetes-config.config-maps=cmap1,cmap2
@ConfigProperty(name = "some.prop1")
String someProp1;
@ConfigProperty(name = "some.prop2")
String someProp2;
If the con g key is a Quarkus con guration le
application.properties/application.yaml, the content is parsed and
each key of the con guration le is used as con g property.
List of Kubernetes Con g parameters.
quarkus.kubernetes-config as pre x is skipped in the next table.
enabled
The application will attempt to look up the con guration from the
API server. (default: false)
fail-on-missing-config
The application will not start if any of the con gured con g
sources cannot be located. (default: true)
config-maps
Con gMaps to look for in the namespace that the Kubernetes
Client has been con gured for. Supports CSV.
namespace
Access to Con gMaps from a speci c namespace.
secrets.enabled
Whether or not con guration can be read from secrets. (default:
false)
Kubernetes Client
Quarkus integrates with Fabric8 Kubernetes Client.
./mvnw quarkus:add-extension
-Dextensions="quarkus-kubernetes-client"
List of Kubernetes client parameters.
quarkus.kubernetes-client as pre x is skipped in the next table.
trust-certs
Trust self-signed certi cates. (default: false)
master-url
URL of Kubernetes API server.
namesapce
Default namespace.
ca-cert-file
CA certi cate data.
client-cert-file
Client certi cate le.
client-cert-data
Client certi cate data.
client-key-data
Client key data.
client-key-algorithm
Client key algorithm.
client-key-passphrase
Client key passphrase.
username
Username.
password
Password.
watch-reconnect-interval
Watch reconnect interval. (default: PT1S)
watch-reconnect-limit
Maximum reconnect attempts. (default: -1)
connection-timeout
Maximum amount of time to wait for a connection. (default:
PT10S)
request-timeout
Maximum amount of time to wait for a request. (default: PT10S)
rolling-timeout
Maximum amount of time to wait for a rollout. (default: PT15M)
http-proxy
HTTP proxy used to access the Kubernetes.
https-proxy
HTTPS proxy used to access the Kubernetes.
proxy-username
Proxy username.
proxy-password
Proxy password.
no-proxy
IP addresses or hosts to exclude from proxying
Or programmatically:
@Dependent
public class KubernetesClientProducer {
@Produces
public KubernetesClient kubernetesClient() {
Config config = new ConfigBuilder()
.withMasterUrl("https://mymaster.com")
.build();
return new DefaultKubernetesClient(config);
}
}
And inject it on code:
@Inject
KubernetesClient client;
ServiceList myServices = client.services().list();
Service myservice = client.services()
.inNamespace("default")
.withName("myservice")
.get();
CustomResourceDefinitionList crds = client
.customResourceDefinitions()
.list();
dummyCRD = new CustomResourceDefinitionBuilder()
...
.build()
client.customResourceDefinitions()
.create(dummyCRD);
Testing
Quarkus provides a Kubernetes Mock test resource that starts a
mock of Kubernetes API server and sets the proper environment
variables needed by Kubernetes Client.
Register next dependency: io.quarkus:quarkus-test-kubernetes-
client:test.
@QuarkusTestResource(KubernetesMockServerTestResource.clas
s)
@QuarkusTest
public class KubernetesClientTest {
@MockServer
private KubernetesMockServer mockServer;
@Test
public void test() {
final Pod pod1 = ...
mockServer
.expect()
.get()
.withPath("/api/v1/namespaces/test/pods")
.andReturn(200,
new PodListBuilder()
.withNewMetadata()
.withResourceVersion("1")
.endMetadata()
.withItems(pod1, pod2)
.build())
.always();
}
}
AWS Lambda
Quarkus integrates with Amazon Lambda.
./mvnw quarkus:add-extension
-Dextensions="io.quarkus:quarkus-amazon-lambda"
And then implement
com.amazonaws.services.lambda.runtime.RequestHandler interface.
public class TestLambda
implements RequestHandler<MyInput, MyOutput> {
@Override
public MyInput handleRequest(MyOutput input,
Context context) {
}
}
The interface
com.amazonaws.services.lambda.runtime.RequestStreamHandler is also
supported.
The interface com.amazon.ask.SkillStreamHandler is also supported.
You can set the handler name by using quarkus.lambda.handler
b h bd h h
annotation.
Test
You can write tests for Amazon lambdas:
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-test-amazon-lambda</artifactId>
<scope>test</scope>
</dependency>
@Test
public void testLambda() {
MyInput in = new MyInput();
in.setGreeting("Hello");
in.setName("Stu");
MyOutput out = LambdaClient.invoke(MyOutput.class, in);
}
To scaffold a AWS Lambda run:
mvn archetype:generate 
-DarchetypeGroupId=io.quarkus 
-DarchetypeArtifactId=quarkus-amazon-lambda-archetype 
-DarchetypeVersion={version}
Azure Functions
Quarkus can make a microservice be deployable to the Azure
Functions.
To scaffold a deployable microservice to the Azure Functions run:
mvn archetype:generate 
-DarchetypeGroupId=io.quarkus 
-DarchetypeArtifactId=quarkus-azure-functions-http-archet
ype 
-DarchetypeVersion={version}
Funqy
Quarkus Funqy is part of Quarkus’s serverless strategy and aims to
provide a portable Java API to write functions deployable to various
FaaS environments like AWS Lambda, Azure Functions, Knative, and
Knative events.
public class GreetingFunction {
@Inject
GreetingService service;
@io.quarkus.funqy.Funq
public String greet(String name) {}
@io.quarkus.funqy.Funq("HelloCustomer")
public String greet(Customer name) {}
@Funq
public Greeting greet(Friend friend,
@io.quarkus.funqy.Context AwsContext ctx) {}
}
In case of Amazon Lambda, only one Funqy function can be
exported per Amazon Lambda deployment. If there is only one
method annotated with @Funq then no prob, if not, you need to set
the function name with quarkus.funqy.export property.
Funqy HTTP
You can invoke on Funqy functions in a pure HTTP environment
with simple adding the Funqy HTTP extension.
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-funqy-http</artifactId>
</dependency>
Funqy Cloud Events
Add the extension:
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-funqy-knative-events</artifactId>
</dependency>
@Funq
public String defaultChain(String input) {}
The Cloud Event type that triggers the function is defaultChain. It
generates a response that triggers a new Cloud Event whose type is
defaultChain.output and the event source is defaultChain.
It can be changed by using the next properties:
quarkus.funqy.knative-events.mapping.defaultChain.trigger=c
onfigChain.output
quarkus.funqy.knative-events.mapping.defaultChain.response-
type=annotated
quarkus.funqy.knative-events.mapping.defaultChain.response-
source=configChain
The properties are of form: quarkus.funqy.knative-events.mapping.
{function name}..
Also can be overriden with
@io.quarkus.funqy.knative.events.CloudEventMapping annotation.
@Funq
@CloudEventMapping(trigger = "annotated", responseSource =
"annotated", responseType = "lastChainLink")
public String annotatedChain(String input) {}
responseType chains annotatedChain response to lastChainLink
function.
@Funq
public void lastChainLink(String input,
@Context io.quarkus.funqy.knative.events.CloudE
vent event) {}
A K-Native Trigger looks like:
apiVersion: eventing.knative.dev/v1alpha1
kind: Trigger
metadata:
name: defaultchain
spec:
filter:
attributes:
type: defaultChain
subscriber:
ref:
apiVersion: serving.knative.dev/v1
kind: Service
name: funqy-knative-events-quickstart
And to curl from inside the Kubernetes cluster:
curl -v "http://default-broker.knativetutorial.svc.cluster.
local" 
-X POST 
-H "Ce-Id: 1234" 
-H "Ce-Specversion: 1.0" 
-H "Ce-Type: defaultChain" 
-H "Ce-Source: curl" 
-H "Content-Type: application/json" 
-d '"Start"'
Apache Camel
Apache Camel Quarkus has its own site:
https://github.com/apache/camel-quarkus
WebSockets
Quarkus can be used to handling web sockets.
./mvnw quarkus:add-extension
-Dextensions="quarkus-websockets"
If you only want the client you can include quarkus-websockets-
client.
And web sockets classes can be used:
@ServerEndpoint("/chat/{username}")
@ApplicationScoped
public class ChatSocket {
@OnOpen
public void onOpen(Session session,
@PathParam("username") String username) {}
@OnClose
public void onClose(..) {}
@OnError
public void onError(..., Throwable throwable) {}
@OnMessage
public void onMessage(...) {}
}
OpenAPI
Quarkus can expose its API description as OpenAPI spec and test it
using Swagger UI.
./mvnw quarkus:add-extension
-Dextensions="io.quarkus:quarkus-smallrye-openapi"
Then you only need to access to /openapi to get OpenAPI v3 spec
of services.
You can update the OpenApi path by setting quarkus.smallrye-
openapi.path property.
Also, in case of starting Quarkus application in dev or test mode,
Swagger UI is accessible at /swagger-ui. If you want to use it in
production mode you need to set quarkus.swagger-ui.always-
include property to true.
You can update the Swagger UI path by setting quarkus.swagger-
ui.path property.
quarkus.swagger-ui.path=/my-custom-path
Possible Swagger UI options with quarkus.swagger-ui pre x:
urls
The urls that will be included as options. (ie quarkus.swagger-
ui.urls.petstore=https://petstore.swagger.io/v2/swagger.json)
urls-primary-name
If urls option is used, this will be the name of the default
selection.
title
The html title for the page.
theme
Swagger UI theme to be used.
footer
A footer for the html page. Nothing by default.
deep-linking
Enables deep linking for tags and operations.
display-operation-id
Controls the display of operationId in operations list.
default-models-expand-depth
The default expansion depth for models.
default-model-expand-depth
The default expansion depth for the model on the model-example
section.
default-model-rendering
Controls how the model is shown when the API is rst rendered.
display-request-duration
Controls the display of the request duration (in milliseconds) for
"Try it out" requests.
doc-expansion
Controls the default expansion setting for the operations and
tags.
filter
Enables ltering.
max-displayed-tags
Limits the number of tagged operations displayed to at most this
many.
operations-sorter
Apply a sort to the operation list of each API. (alpha, method,
function)
h t i
Controls the display of vendor extension.
show-common-extensions
Controls the display of extensions.
tag-sorter
Apply a sort to the tag list of each API.
on-complete
Provides a mechanism to be noti ed when Swagger UI has
nished rendering a newly provided de nition.
syntax-highlight
Set to false to deactivate syntax highlighting of payloads and
cURL command.
oauth2-redirect-url
OAuth redirect URL.
request-interceptor
Function to intercept remote de nition, "Try it out", and OAuth 2.0
requests.
request-curl-options
Array of command line options available to the curl command.
response-interceptor
Function to intercept remote de nition, "Try it out", and OAuth 2.0
responses.
show-mutated-request
Uses the mutated request returned from a requestInterceptor to
produce the curl command in the UI.
supported-submit-methods
List of HTTP methods that have the "Try it out" feature enabled.
validator-url
Swagger UI attempts to validate specs against swagger.io’s
online validator.
with-credentials
Enables passing credentials, as de ned in the Fetch standard, in
CORS requests that are sent by the browser.
model-property-macro
Function to set default values to each property in model.
parameter-macro
Function to set default value to parameters.
persist-authorization
It persists authorization data and it would not be lost on browser
close/refresh.
layout
The name of a component available via the plugin system to use
as the top-level layout for Swagger UI.
plugins
A list of plugin functions to use in Swagger UI.
presets
A list of presets to use in Swagger UI.
You can customize the output by using Open API v3 annotations.
@Schema(name="Developers",
description="POJO that represents a developer.")
public class Developer {
@Schema(required = true, example = "Alex")
private String name;
}
@POST
@Path("/developer")
@Operation(summary = "Create deeloper",
description = "Only be done by admin.")
public Response createDeveloper(
@RequestBody(description = "Developer object",
required = true,
content = @Content(schema =
@Schema(implementation = Developer.class)))
Developer developer)
All possible annotations can be seen at
org.eclipse.micropro le.openapi.annotations package.
You can also serve OpenAPI Schema from static les instead of
dynamically generated from annotation scanning.
You need to put OpenAPIdocumentation under META-INF directory
(ie: META-INF/openapi.yaml).
A request to /openapi will serve the combined OpenAPI document
from the static le and the generated from annotations. You can
disable the scanning documents by adding the next con guration
property: mp.openapi.scan.disable=true.
Other valid document paths are: META-INF/openapi.yml, META-
INF/openapi.json, WEB-INF/classes/META-INF/openapi.yml, WEB-
INF/classes/META-INF/openapi.yaml, WEB-INF/classes/META-
INF/openapi.json.
You can store generated OpenAPI schema if quarkus.swagger-
ui.store-schema-directory is set.
Possible OpenAPI options with quarkus.smallrye-openapi pre x:
path
The path at which to register the OpenAPI Servlet. (default:
openapi)
store-schema-directory
The generated OpenAPI schema documents will be stored here
on build.
always-run-filter
Do not run the lter only at startup, but every time the document
is requested (dynamic). (default: false)
ignore-static-document
Do not include the provided static openapi document. (default:
false)
additional-docs-directory
A list of local directories that should be scanned for yaml and/or
json les to be included in the static model.
security-scheme
Add a certain SecurityScheme with con g. (basic, jwt, oidc,
oauth2Implicit)
security-scheme-name
Add a Security Scheme name to the generated OpenAPI
document. (default: SecurityScheme)
security-scheme-description
Add a description to the Security Scheme. (default:
Authentication)
basic-security-scheme-value
Add a scheme value to the Basic HTTP Security Scheme.
(default: basic)
jwt-security-scheme-value
Add a scheme value to the JWT Security Scheme. (default:
bearer)
jwt-bearer-format
Add a bearer format to the JWT Security Scheme. (default: JWT)
oidc-open-id-connect-url
Add a openIdConnectUrl value to the OIDC Security Scheme
oauth2-implicit-refresh-url
Add a implicit ow refreshUrl value to the OAuth2 Security
Scheme
oauth2-implicit-authorization-url
Add an implicit ow authorizationUrl value to the OAuth2 Security
Scheme
oauth2-implicit-token-url
Add an implicit ow tokenUrl value to the OAuth2 Security
Scheme
open-api-version
Override the openapi version in the Schema document
info-title
Set the title in Info tag in the Schema document
info-version
Set the version in Info tag in the Schema document
info-description
Set the description in Info tag in the Schema document
info-terms-of-service
Set the terms of the service in Info tag in the Schema document
info-contact-email
Set the contact email in Info tag in the Schema document
info-contact-name
Set the contact name in Info tag in the Schema document
info-contact-url
Set the contact url in Info tag in the Schema document
info-license-name
Set the license name in Info tag in the Schema document
info-license-url
Set the license url in Info tag in the Schema document
operation-id-strategy
Set the strategy to automatically create an operation Id. Possible
values: method,class-method, package-class-method
Mail Sender
You can send emails by using Quarkus Mailer extension:
./mvnw quarkus:add-extension
-Dextensions="io.quarkus:quarkus-mailer"
You can inject two possible classes io.quarkus.mailer.Mailer for
synchronous API or io.quarkus.mailer.reactive.ReactiveMailer for
asynchronous/reactive API.
@Inject
Mailer mailer;
And then you can use them to send an email:
mailer.send(
Mail.withText("to@acme.org", "Subject", "Body")
);
Reactive Mail client
@Inject
ReactiveMailer reactiveMailer;
CompletionStage<Response> stage =
reactiveMailer.send(
Mail.withText("to@acme.org", "Subject", "Body")
)
.subscribeAsCompletionStage()
.thenApply(x -> Response.accepted().build());
If you are using quarkus-resteasy-mutiny, you can return
io.smallrye.mutiny.Uni type.
Mail class contains methods to add cc, bcc, headers, bounce
address, reply to, attachments, inline attachments and html body.
mailer.send(Mail.withHtml("to@acme.org", "Subject", body)
.addInlineAttachment("quarkus.png",
new File("quarkus.png"),
"image/png", "<my-image@quarkus.io>"));
If you need deep control you can inject Vert.x mail client
@Inject MailClient client;
You need to con gure SMTP properties to be able to send an email:
quarkus.mailer.from=test@quarkus.io
quarkus.mailer.host=smtp.sendgrid.net
quarkus.mailer.port=465
quarkus.mailer.ssl=true
quarkus.mailer.username=....
quarkus.mailer.password=....
List of Mailer parameters. quarkus. as a pre x is skipped in the next
table.
Parameter Default Description
mailer.from Default address.
mailer.mock
false in prod, true in
dev and test.
Emails not sent, just
printed and stored in
a MockMailbox.
mailer.bounce-
address
Default address.
mailer.host mandatory SMTP host.
mailer.port 25 SMTP port.
mailer.username The username.
mailer.password The password.
mailer.ssl false Enables SSL.
mailer.trust-all false Trust all certi cates.
mailer.max-pool-size 10
Max open
connections .
Parameter Default Description
mailer.own-host-name
Hostname for
HELO/EHLO and
Message-ID
mailer.keep-alive true
Connection pool
enabled.
mailer.disable-esmtp false Disable ESMTP.
mailer.start-tls OPTIONAL
TLS security mode.
DISABLED, OPTIONAL,
REQUIRED.
mailer.login NONE
Login mode. NONE,
OPTIONAL, REQUIRED.
mailer.auth-methods All methods. Space-separated list.
mailer.key-store Path of the key store.
mailer.key-store-
password
Key store password.
if you enable SSL for the mailer and you want to build a
native executable, you will need to enable the SSL support
quarkus.ssl.native=true.
Testing
If quarkus.mailer.mock is set to true, which is the default value in
dev and test mode, you can inject MockMailbox to get the sent
messages.
@Inject
MockMailbox mailbox;
@BeforeEach
void init() {
mailbox.clear();
}
List<Mail> sent = mailbox
.getMessagesSentTo("to@acme.org");
Scheduled Tasks
You can schedule periodic tasks with Quarkus.
@ApplicationScoped
public class CounterBean {
@Scheduled(every="10s", delayed="1s")
void increment() {}
@Scheduled(cron="0 15 10 * * ?")
void morningTask() {}
}
every and cron parameters can be surrounded with {} and the
value is used as con g property to get the value.
@Scheduled(cron = "${morning.check.cron.expr}")
void morningTask() {}
@Scheduled(cron = "${myMethod.cron.expr:0 0 15 ? * MON *}")
void myMethod() {}
And con gure the property into application.properties:
morning.check.cron.expr=0 15 10 * * ?
morning.check.cron.expr=disabled
By default Quarkus expresion is used, but you can change that by
setting quarkus.scheduler.cron-type property.
quarkus.scheduler.cron-type=unix
org.quartz.Scheduler can be injected as any other bean and
scehdule jobs programmatically.
@Inject
org.quartz.Scheduler quartz;
quartz.scheduleJob(job, trigger);
Quarkus provides a built-in bean of type
io.quarkus.scheduler.Scheduler:
@Inject
io.quarkus.scheduler.Scheduler scheduler;
scheduler.pause(); // Pause all
scheduler.pause("myIdentity"); // Pause a specific schedule
d method by its identity
scheduler.resume("myIdentity");
scheduler.resume()
Kogito
Quarkus integrates with Kogito, a next-generation business
automation toolkit from Drools and jBPM projects for adding
business automation capabilities.
To start using it you only need to add the next extension:
./mvnw quarkus:add-extension
-Dextensions="kogito"
DevServices
When testing or running in dev mode Quarkus can even provide you
with a zero con g Kogito out of the box.
Possible con guration values pre xed with quarkus.kogito:
devservices.enabled
If devservices is enabled or not. (default: true)
devservices.image-name
The container image name to use instead of the default one.
(default: quay.io/kiegroup/kogito-data-index-ephemeral)
devservices.port
Optional xed port the dev service will listen to. (default: 8180)
devservices.shared
Indicates if the Data Index instance managed by Quarkus Dev
Services is shared. When shared, Quarkus looks for running
containers using label-based service discovery. (default: true)
devservices.service-name
The value of the kogito-dev-service-data-index label attached to
the started container. (default: kogito-data-index)
Apache Tika
Quarkus integrates with Apache Tika to detect and extract
metadata/text from different le types:
./mvnw quarkus:add-extension
-Dextensions="quarkus-tika"
@Inject
io.quarkus.tika.TikaParser parser;
@POST
@Path("/text")
@Consumes({ "text/plain", "application/pdf",
"application/vnd.oasis.opendocument.text" })
@Produces(MediaType.TEXT_PLAIN)
public String extractText(InputStream stream) {
return parser.parse(stream).getText();
}
You can con gure Apache Tika in application.properties le by
using next properties pre xed with k :
Parameter Default Description
tika.tika-config-
path
tika-config.xml
Path to the Tika
con guration
resource.
quarkus.tika.parsers
CSV of the
abbreviated or full
parser class to be
loaded by the
extension.
tika.append-embedded-
content
true
The document may
have other embedded
documents. Set if
autmatically append.
JGit
Quarkus integrates with JGit to integrate with Git repositories:
./mvnw quarkus:add-extension
-Dextensions="quarkus-jgit"
And then you can start using JGit:
try (Git git = Git.cloneRepository()
.setDirectory(tmpDir)
.setURI(url)
.call()) {
return tmpDir.toString();
}
When running in native mode, make sure to con gure SSL
access correctly quarkus.ssl.native=true (Native and SSL).
Web Resources
You can serve web resources with Quarkus. You need to place web
resources at src/main/resources/META-INF/resources and then they
are accessible (ie http://localhost:8080/index.html)
By default static resources as served under the root context. You
can change this by using quarkus.http.root-path property.
Transactional Memory
Quarkus integrates with the Software Transactional Memory (STM)
implementation provided by the Narayana project.
./mvnw quarkus:add-extension
-Dextensions="narayana-stm"
Transactional objects must be interfaces and annotated with
org.jboss.stm.annotations.Transactional.
@Transactional
@NestedTopLevel
public interface FlightService {
int getNumberOfBookings();
void makeBooking(String details);
}
The pessimistic strategy is the default one, you can change to
optimistic by using @Optimistic.
Then you need to create the object inside org.jboss.stm.Container.
Container<FlightService> container = new Container<>();
FlightServiceImpl instance = new FlightServiceImpl();
FlightService flightServiceProxy = container.create(instanc
e);
The implementation of the service sets the locking and what needs
to be saved/restored:
import org.jboss.stm.annotations.ReadLock;
import org.jboss.stm.annotations.State;
import org.jboss.stm.annotations.WriteLock;
public class FlightServiceImpl
implements FlightService {
@State
private int numberOfBookings;
@ReadLock
public int getNumberOfBookings() {
return numberOfBookings;
}
@WriteLock
public void makeBooking(String details) {
numberOfBookings += 1;
}
}
Any member is saved/restored automatically (@State is not
mandatory). You can use @NotState to avoid behaviour.
Transaction boundaries
Declarative
@NestedTopLevel: De nes that the container will create a new
top-level transaction for each method invocation.
@Nested: De nes that the container will create a new top-level
or nested transaction for each method invocation.
Programmatically
AtomicAction aa = new AtomicAction();
aa.begin();
{
try {
flightService.makeBooking("BA123 ...");
taxiService.makeBooking("East Coast Taxis ...");
aa.commit();
} catch (Exception e) {
aa.abort();
}
}
Quartz
Quarkus integrates with Quartz to schedule periodic clustered
tasks.
./mvnw quarkus:add-extension
-Dextensions="quartz"
@ApplicationScoped
public class TaskBean {
@Transactional
@Scheduled(every = "10s")
void schedule() {
Task task = new Task();
task.persist();
}
}
To con gure in clustered mode vida DataSource:
quarkus.datasource.url=jdbc:postgresql://localhost/quarkus_
test
quarkus.datasource.driver=org.postgresql.Driver
# ...
quarkus.quartz.clustered=true
quarkus.quartz.store-type=db
You need to de ne the datasource used by clustered mode
and also import the database tables following the Quartz
schema.
Quartz can be con gured usinf the following properties with
quarkus.quartz pre x:
clustered
Enable cluster mode or not.
store-type
The type of store to use. Possible values: ram, db (default: ram)
datasource
The name of the datasource to use.
table-prefix
The pre x for quartz job store tables. (default: QRTZ_)
trigger-listeners.<name>.class
Class name for the trigger.
trigger-listeners.<name>.property-name
The properties passed to the class.
job-listeners.<name>.class
Class name for the job.
job-listeners.<name>.property-name
The properties passed to the class.
plugins.<name>.class
Class name for the plugin.
plugins.<name>.property-name
The properties passed to the class.
instance-name
The name of the Quartz instance. (default:
QuarkusQuartzScheduler)
thread-count
The size of scheduler thread pool. (default: 25)
thread-priority
Thread priority of worker threads in the pool. (default: 5)
force-start
The scheduler will be started even if no scheduled business
methods are found.
start-mode
Scheduler can be started in different modes: normal, forced or
halted. (default: normal)
Qute
Qute is a templating engine designed speci cally to meet the
Quarkus needs. Templates should be placed by default at
src/main/resources/templates aand subdirectories.
./mvnw quarkus:add-extension
-Dextensions="quarkus-resteasy-qute"
Templates can be de ned in any format, in case of HTML:
item.html
{@org.acme.Item item}
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>{item.name}</title>
</head>
<body>
<h1>{item.name ?: 'Unknown'}</h1>
<h2>{str:reverse('Hello')}</h2>
<div>Price: {item.price}</div>
{#if item.price > 100}
<div>Discounted Price: {item.discountedPrice}</div>
{/if}
</body>
</html>
First line is not mandatory but helps on doing property checks at
compilation time.
Including templates passing parameters:
<html>
<head>
<meta charset="UTF-8">
<title>Simple Include</title>
</head>
<body>
{#include foo limit=10 /}
</body>
</html>
To render the template:
public class Item {
public String name;
public BigDecimal price;
}
@Inject
io.quarkus.qute.Template item;
@GET
@Path("{id}")
@Produces(MediaType.TEXT_HTML)
public TemplateInstance get(@PathParam("id") Integer id) {
return item.data("item", service.findItem(id));
}
@TemplateExtension
static BigDecimal discountedPrice(Item item) {
return item.price.multiply(new BigDecimal("0.9"));
}
@TemplateExtension(namespace = "str")
public static class StringExtensions {
static String reverse(String val) {
return new StringBuilder(val).reverse().toString();
}
}
If @ResourcePath is not used in Template then the name of the eld is
used as le name. In this case the le should be
src/main/resources/templates/item.{}. Extension of the le is not
required to be set.
discountedPrice is not a eld of the POJO but a method call.
Method de nition must be annotated with @TemplateExtension and
be static method. First parameter is used to match the base object
(Item). @TemplateExtension can be used at class level:
@TemplateExtension
public class MyExtensions {
static BigDecimal discountedPrice(Item item) {
return item.price.multiply(new BigDecimal("0.9"));
}
}
Methods with multiple parameters are supported too:
{item.discountedPrice(2)}
static BigDecimal discountedPrice(Item item, int scale) {
return item.price.multiply(scale);
}
Qute for syntax supports any instance of Iterable, Map.EntrySet,
Stream or Integer.
{#for i in total}
{i}:
{/for}
The next map methods are supported:
{#for key in map.keySet}
{#for value in map.values}
{map.size}
{#if map.isEmpty}
{map['foo']
The next list methods are supported:
{list[0]}
The next number methods are supported:
{#if counter.mod(5) == 0}
Switch/When
{#switch person.name}
{#case 'John'}
Hey John!
{#case 'Mary'}
Hey Mary!
{/switch}
{#when items.size}
{#is 1} (1)
There is exactly one item!
{#is > 10} (2)
There are more than 10 items!
{#else} (3)
There are 2 -10 items!
{/when}
Following operators can be used either in when and switch: not, ne,
!=, gt, >, ge, >=, lt, <, le, <=, in, ni, !in.
eval
{#eval myData.template name='Mia' /}
The result of myData.template will be used as the template.
Message Bundling
@io.quarkus.qute.i18n.MessageBundle
public interface AppMessages {
@io.quarkus.qute.i18n.Message("Hello {name}!")
String hello_name(String name);
}
There are 3 methods to inject the message:
MessageBundles.get(AppMessages.class).hello_name("Lucie");
or
@Inject AppMessages app;
app.hello_name("Lucie");
or
<p>{msg:hello_name('Lucie')}</p>
Localization
There are two ways to set localized message:
@io.quarkus.qute.i18n.Localized("de")
public interface GermanAppMessages {
@Override
@io.quarkus.qute.i18n.Message("Hallo {name}!")
String hello_name(String name);
}
or
msg_de.properties
hello_name=Hallo {name}!
You can render programmaticaly the templates too:
// file located at src/main/resources/templates/reports/v1/
report_01.{}
@ResourcePath("reports/v1/report_01")
Template report;
String output = report
.data("samples", service.get())
.render();
Value Resolvers
Value resolvers are invoked when evaluating expressions.
void configureEngine(@Observes EngineBuilder builder) {
builder.addValueResolver(ValueResolver.builder()
.appliesTo(ctx -> ctx.getBase() instanceof Long && ct
x.getName().equals("tenTimes"))
.resolveSync(ctx -> (Long) ctx.getBase() * 10)
.build());
}
Content Filters
Content lters can be used to modify the template contents before
parsing.
void configureEngine(@Observes EngineBuilder builder) {
builder.addParserHook(new ParserHook() {
@Override
public void beforeParsing(ParserHelper parserHelper)
{
parserHelper.addContentFilter(contents -> content
s.replace("${", "${"));
}
});
}
Reactive and Async
CompletionStage<String> async = report.renderAsync();
Multi<String> publisher = report.createMulti();
Uni<String> content = io.smallrye.mutiny.Uni.createFrom()
.completionStage(() -> report.r
enderAsync());
Qute Mail Integration
@Inject
MailTemplate hello;
CompletionStage<Void> c = hello.to("to@acme.org")
.subject("Hello from Qute template")
.data("name", "John")
.send();
INFO: Template located at src/main/resources/templates/hello.
[html|txt].
Sentry
Quarkus integrates with Sentry for logging errors into an error
monitoring system.
./mvnw quarkus:add-extension
-Dextensions="quarkus-logging-sentry"
And the con guration to send all errors occuring in the package
org.example to Sentrty with DSN https://abcd@sentry.io/1234:
quarkus.log.sentry=true
quarkus.log.sentry.dsn=https://abcd@sentry.io/1234
quarkus.log.sentry.level=ERROR
quarkus.log.sentry.in-app-packages=org.example
Full list of con guration properties having quarkus.log as pre x:
sentry.enable
Enable the Sentry logging extension (default: false)
sentry.dsn
Where to send events.
sentry.level
Log level (default: WARN)
sentry.server-name
Sets the server name that will be sent with each event.
sentry.in-app-packages
Con gure which package pre xes your application uses.
JSch
Quarkus integrates with Jsch for SSH communication.
./mvnw quarkus:add-extension
-Dextensions="quarkus-jsch"
JSch jsch = new JSch();
Session session = jsch.getSession(null, host, port);
session.setConfig("StrictHostKeyChecking", "no");
session.connect();
Cache
Quarkus can cache method calls by using as key the tuple (method
+ arguments).
./mvnw quarkus:add-extension
-Dextensions="cache"
@io.quarkus.cache.CacheResult(cacheName = "weather-cache")
public String getDailyForecast(LocalDate date, String city)
{}
@CacheInvalidate removes the element represented by the
calculated cache key from cache. @CacheInvalidateAll removes all
entries from the cache. @CacheKey to speci cally set the arguments
b d k d f ll
@ApplicationScoped
public class CachedBean {
@CacheResult(cacheName = "foo")
public Object load(Object key) {}
@CacheInvalidate(cacheName = "foo")
public void invalidate(Object key) {}
@CacheInvalidateAll(cacheName = "foo")
public void invalidateAll() {}
}
Programmatic API
@Inject
CacheManager cacheManager;
@Inject
@CacheName("my-cache")
Cache cache;
public Uni<String> getNonBlockingExpensiveValue(Object key)
{
return cache.get(key, k -> {
});
}
public String getBlockingExpensiveValue(Object key) {
return cache.get(key, k -> {
}).await().indefinitely(); (4)
}
You can disable the caching system by setting
quarkus.cache.enabled property to false.
This extension uses Caffeine as its underlying caching provider.
Each cache can be con gured individually:
quarkus.cache.caffeine."foo".initial-capacity=10
quarkus.cache.caffeine."foo".maximum-size=20
quarkus.cache.caffeine."foo".expire-after-write
quarkus.cache.caffeine."bar".maximum-size=1000
Full list of con guration properties having quarkus.cache.caffeine.
[cache-name] as pre x:
initial-capacity
Minimum total size for the internal data structures.
maximum-size
Maximum number of entries the cache may contain.
expire-after-write
Speci es that each entry should be automatically removed from
the cache once a xed duration has elapsed after the entry’s
creation or last write
expire-after-access
Speci es that each entry should be automatically removed from
the cache once a xed duration has elapsed after the entry’s
creation, or last write.
You can multiple cache annotations on a single method.
If you see a javax.enterprise.context.ContextNotActiveException,
you need to add the quarkus-smallrye-context-propagation
extension.
Banner
Banner is printed by default. It is not an extension but placed in the
core.
quarkus.banner.path
Path is relative to root of the classpath. (default:
default_banner.txt)
quarkus.banner.enabled
Enables banner. (default : true)
OptaPlanner
Quarkus integrates with OptaPlanner.
./mvnw quarkus:add-extension
-Dextensions="quarkus-optaplanner, quarkus-optaplanner-ja
ckson"
@PlanningSolution
public class TimeTable {
}
@Inject
private SolverManager<TimeTable, UUID> solverManager;
UUID problemId = UUID.randomUUID();
SolverJob<TimeTable, UUID> solverJob = solverManager.solve
(problemId, problem);
TimeTable solution = solverJob.getFinalBestSolution();
Possible con guration options pre xed with quarkus.optaplanner:
solver-config-xml
A classpath resource to read the solver con guration XML. Not
mandatory.
solver.environment-mode
Enable runtime assertions to detect common bugs in your
implementation during development. Possible values:
FAST_ASSERT, FULL_ASSERT, NON_INTRUSIVE_FULL_ASSERT,
NON_REPRODUCIBLE, REPRODUCIBLE. (default: REPRODUCIBLE)
solver.move-thread-count
Enable multithreaded solving for a single problem. Possible
values: MOVE_THREAD_COUNT_NONE, MOVE_THREAD_COUNT_AUTO, a number
or formula based on the available processors. (default:
MOVE_THREAD_COUNT_NONE)
solver.termination.spent-limit
How long the solver can run. (ie 5s)
solver.termination.unimproved-spent-limit
How long the solver can run without nding a new best solution
after nding a new best solution. (ie 2h)
solver.termination.best-score-limit
Terminates the solver when a speci c or higher score has been
reached. (ie 0hard/-1000soft)
solver-manager.parallel-solver-count
The number of solvers that run in parallel. (default:
PARALLEL_SOLVER_COUNT_AUTO)
Context Propagation
./mvnw quarkus:add-extension
-Dextensions="quarkus-smallrye-context-propagation"
If using mutiny extension together you already get context
propagation for ArC, RESTEasy and transactions. With
CompletionStage you need to:
@Inject ThreadContext threadContext;
@Inject ManagedExecutor managedExecutor;
threadContext.withContextCapture(..)
.thenApplyAsync(r -> {}, managedExecutor);
If you are going to use security in a reactive environment you will
likely need Smallrye Content Propagation to propagate the identity
throughout the reactive callback.
Con guration from HasiCorp Consul
You can read runtime con guration from HashiCorp Consul.
./mvnw quarkus:add-extension
-Dextensions="consul-config"
You need to con gure Consul:
quarkus.consul-config.enabled=true
quarkus.consul-config.agent.host-port=localhost:8500
quarkus.consul-config.properties-value-keys=config/consul-t
est
@ConfigProperty(name = "greeting.message")
String message;
In Consul:
"Key": "config/consul-test",
"Value": "greeting.message=Hello from Consul"
Possible con guration parameters, pre xed with quarkus.consul-
config:
enabled
The application will attempt to look up the con guration from
Consul. (default: false)
prefix
Common pre x that all keys share when looking up the keys from
Consul. The pre x is not included in the keys of the user
con guration
raw-value-keys
Keys whose value is a raw string. The keys that end up in the user
con guration are the keys speci ed her with '/' replaced by '.'
properties-value-keys
Keys whose value represents a properties-like le conttent.
fail-on-missing-key
If the application will not start if any of the con gured con g
sources cannot be located. (default: true)
trust-store
TrustStore to be used containing the SSL certi cate used by
Consul agent.
trust-store-password
Password of TrustStore to be used containing the SSL certi cate
used by Consul agent.
key-password
Password to recover key from KeyStore for SSL client
authentication with Consul agent.
agent.host-port
Consul agent host. (default: localhost:8500)
agent.use-https
Use HTTPS when communicating with the agent. (default: false)
agent.token
Consul token to be provided when authentication is enabled.
agent.key-store
KeyStore (classpath or lesystem) to be used containing the SSL
certi cate used by Consul agent.
agent.key-store-password
Password of KeyStore.
agent.trust-certs
To trust all certi cates or not.
agent.connection-timeout
Connection timeout. (default: 10S)
agent.read-timeout
Reading timeout. (default: 60S)
Amazon Alexa
You can use Amazon Alexa by adding the extension:
./mvnw quarkus:add-extension
-Dextensions="quarkus-amazon-alexa"
WebJar Locator
To change how you can refer to webjars skipping the version part
you can use WebJars locator extension.
./mvnw quarkus:add-extension
-Dextensions="webjars-locator"
Then the JavaScript location is changed from
/webjars/jquery/3.1.1/jquery.min.js to
/webjars/jquery/jquery.min.js in your HTML les.
Amazon SES
mvn quarkus:add-extension
-Dextensions="amazon-ses"
@Inject
software.amazon.awssdk.services.ses.SesClient sesClient;
@Inject
software.amazon.awssdk.services.ses.SesAsyncClient sesClien
t;
quarkus.ses.endpoint-override=http://localhost:8012
quarkus.ses.aws.region=us-east-1
quarkus.ses.aws.credentials.type=static
quarkus.ses.aws.credentials.static-provider.access-key-id=t
est-key
quarkus.ses.aws.credentials.static-provider.secret-access-k
ey=test-secret
You need to set a HTTP client either URL Connection:
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>url-connection-client</artifactId>
</dependency>
or Apache HTTP:
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>apache-client</artifactId>
</dependency>
quarkus.ses.sync-client.type=apache
Or async:
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>netty-nio-client</artifactId>
</dependency>
Con guration properties are the same as Amazon DynamoDB but
changing the pre x from dynamodb to ses.
Jbang
Creating an initial script:
jbang scripting/quarkusapp.java
Adding Quarkus dependencies in script:
//DEPS io.quarkus:quarkus-resteasy:{quarkus-version}
Put some Quarkus CLI code:
@Path("/hello")
@ApplicationScoped
public class quarkusapp {
@GET
public String sayHello() {
return "hello";
}
public static void main(String[] args) {
Quarkus.run(args);
}
}
To run the script:
jbang quarkusapp.java
A Maven goal is provided to scaffold a project:
mvn io.quarkus:quarkus-maven-plugin:<version>:create-jbang
Narayana LRA
The LRA (short for Long Running Action) participant extension is
useful in microservice based designs where different services can
bene t from a relaxed notion of distributed consistency.
The extension integrates with MicroPro le LRA
./mvnw quarkus:add-extension
-Dextensions="narayana-lra"
The only LRA speci c property is quarkus.lra.coordinator-url=<url>
which speci es the HTTP endpoint of an external coordinator,
@Path("/")
@ApplicationScoped
public class SimpleLRAParticipant
{
@LRA(LRA.Type.REQUIRES_NEW)
@Path("/work")
@PUT
public void doInNewLongRunningAction(@HeaderParam(LRA_HTT
P_CONTEXT_HEADER) URI lraId)
{
}
@org.eclipse.microprofile.lra.annotation.Complete
@Path("/complete")
@PUT
public Response completeWork(@HeaderParam(LRA_HTTP_CONTEX
T_HEADER) URI lraId,
String userData)
{
return Response.ok(ParticipantStatus.Completed.name()).
build();
}
@org.eclipse.microprofile.lra.annotation.Compensate
@Path("/compensate")
@PUT
public Response compensateWork(@HeaderParam(LRA_HTTP_CONT
EXT_HEADER) URI lraId,
String userData)
{
return Response.ok(ParticipantStatus.Compensated.name
()).build();
}
}
@LRA can be used in differrent methods, so it’s started in one
method and nished in another resource using end attribute:
@LRA(value = LRA.Type.REQUIRED, // if there is no incoming
context a new one is created
cancelOn = {
Response.Status.INTERNAL_SERVER_ERROR // cancel on
a 500 code
},
cancelOnFamily = {
Response.Status.Family.CLIENT_ERROR // cancel on an
y 4xx code
},
end = false) // the LRA will continue to run when the m
ethod finishes
@LRA(LRA.Type.MANDATORY, // requires an active context befo
re method can be executed
end = true)
Spring DI
Quarkus provides a compatibility layer for Spring dependency
injection.
./mvnw quarkus:add-extension
-Dextensions="quarkus-spring-di"
Some examples of what you can do. Notice that annotations are
the Spring original ones.
@Configuration
public class AppConfiguration {
@Bean(name = "capitalizeFunction")
public StringFunction capitalizer() {
return String::toUpperCase;
}
}
Or as a component:
@Component("noopFunction")
public class NoOpSingleStringFunction
implements StringFunction {
}
Also as a service and injection properties from
application.properties.
@Service
public class MessageProducer {
@Value("${greeting.message}")
String message;
}
And you can inject using Autowired or constructor in a component
and in a JAX-RS resource too.
@Component
public class GreeterBean {
private final MessageProducer messageProducer;
@Autowired @Qualifier("noopFunction")
StringFunction noopStringFunction;
public GreeterBean(MessageProducer messageProducer) {
this.messageProducer = messageProducer;
}
}
Spring Boot Con guration
Quarkus provides a compatibility layer for Spring Boot
ConfigurationProperties.
./mvnw quarkus:add-extension
-Dextensions="quarkus-spring-boot-properties"
@ConfigurationProperties("example")
public final class ClassProperties {
private String value;
private AnotherClass anotherClass;
// getters/setters
}
example.value=class-value
example.anotherClass.value=true
Spring Cloud Con g Client
Quarkus integrates Spring Cloud Con g Client and MicroPro le
Con g spec.
./mvnw quarkus:add-extension
-Dextensions="quarkus-spring-cloud-config-client"
You need to con gure the extension:
quarkus.spring-cloud-config.uri=http://localhost:8089
quarkus.spring-cloud-config.username=user
quarkus.spring-cloud-config.password=pass
quarkus.spring-cloud-config.enabled=true
@ConfigProperty(name = "greeting.message")
String greeting;
Pre x is quarkus.spring-cloud-config.
uri
Base URI where the Spring Cloud Con g Server is available.
(default: localhost:8888)
username
Username to be used if the Con g Server has BASIC Auth
enabled.
password
Password to be used if the Con g Server has BASIC Auth
enabled.
enabled
Enables read con guration from Spring Cloud Con g Server.
(default: false)
fail-fast
True to not start application if cannot access to the server.
(default: false)
connection-timeout
The amount of time to wait when initially establishing a
connection before giving up and timing out. (default: 10S)
read-timeout
The amount of time to wait for a read on a socket before an
exception is thrown. (default: 60S)
label
The label to be used to pull remote con guration properties.
Spring Web
Quarkus provides a compatibility layer for Spring Web.
./mvnw quarkus:add-extension
-Dextensions="quarkus-spring-web"
Speci cally supports the REST related features. Notice that
infrastructure things like BeanPostProcessor will not be executed.
@RestController
@RequestMapping("/greeting")
public class GreetingController {
private final GreetingBean greetingBean;
public GreetingController(GreetingBean greetingBean) {
this.greetingBean = greetingBean;
}
@GetMapping("/{name}")
public Greeting hello(@PathVariable(name = "name")
String name) {
return new Greeting(greetingBean.greet(name));
}
}
Supported annotations are: RestController, RequestMapping,
GetMapping, PostMapping, PutMapping, DeleteMapping, PatchMapping,
RequestParam, RequestHeader, MatrixVariable, PathVariable,
CookieValue, RequestBody, ResponseStatus, ExceptionHandler and
RestControllerAdvice.
If you scaffold the project with spring-web extension, then
Spring Web annotations are sed in the generated project.
mvn io.quarkus:quarkus-maven-plugin:2.7.0.Final:create … -
Dextensions="spring-web".
The next return types are supported:
org.springframework.http.ResponseEntity and java.util.Map.
The next parameter types are supported: An Exception argument
and ServletRequest/HttpServletRequest (adding quarkus-undertow
dependency).
Spring Data JPA
While users are encouraged to use Hibernate ORM with Panache
for Relational Database access, Quarkus provides a compatibility
layer for Spring Data JPA repositories.
./mvnw quarkus:add-extension
-Dextensions="quarkus-spring-data-jpa"
INFO: Of course you still need to add the JDBC driver, and con gure
it in application.properties.
public interface FruitRepository
extends CrudRepository<Fruit, Long> {
List<Fruit> findByColor(String color);
}
And then you can inject it either as shown in Spring DI or in Spring
Web.
Interfaces supported:
org.springframework.data.repository.Repository
org.springframework.data.repository.CrudRepository
org.springframework.data.repository.PagingAndSortingReposito
ry
org.springframework.data.jpa.repository.JpaRepository.
INFO: Generated repositories are automatically annotated with
@Transactional.
Repository fragments is also supported:
public interface PersonRepository
extends JpaRepository<Person, Long>, PersonFragment {
void makeNameUpperCase(Person person);
}
User de ned queries:
@Query("select m from Movie m where m.rating = ?1")
Iterator<Movie> findByRating(String rating);
@Modifying
@Query("delete from Movie where rating = :rating")
void deleteByRating(@Param("rating") String rating);
@Query(value = "SELECT COUNT(*), publicationYear FROM Book
GROUP BY publicationYear")
List<BookCountByYear> findAllByPublicationYear2();
interface BookCountByYear {
int getPublicationYear();
Long getCount();
}
What is currently unsupported:
Methods of
org.springframework.data.repository.query.QueryByExampleExec
utor
QueryDSL support
Customizing the base repository
java.util.concurrent.Future as return type
Native and named queries when using @Query
Spring Data Rest
While users are encouraged to use REST Data with Panache for the
REST data access endpoints generation, Quarkus provides a
compatibility layer for Spring Data REST in the form of the spring-
data-rest extension.
./mvnw quarkus:add-extension
-Dextensions="spring-data-rest"
import java.util.Optional;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.rest.core.annotation.Reposi
toryRestResource;
import org.springframework.data.rest.core.annotation.RestRe
source;
@RepositoryRestResource(exported = false, path = "/my-fruit
s")
public interface FruitsRepository extends CrudRepository<Fr
uit, Long> {
@RestResource(exported = true)
Optional<Fruit> findById(Long id);
@RestResource(exported = true)
Iterable<Fruit> findAll();
}
The spring-data-jpa extension will generate an implementation for
this repository. Then the spring-data-rest extension will generate a
REST CRUD resource for it.
The following interfaces are supported:
org.springframework.data.repository.CrudRepository
org.springframework.data.repository.PagingAndSortingReposito
ry
org.springframework.data.jpa.repository.JpaRepository
Spring Security
Quarkus provides a compatibility layer for Spring Security.
./mvnw quarkus:add-extension
-Dextensions="spring-security"
You need to choose a security extension to de ne user, roles, …
such as openid-connect, oauth2, properties-file or security-jdbc
as seen at RBAC.
Then you can use Spring Security annotations to protect the
methods:
@Secured("admin")
@GetMapping
public String hello() {
return "hello";
}
Quarkus provides support for some of the most used features of
Spring Security’s @PreAuthorize annotation.
Some examples:
hasRole
@PreAuthorize("hasRole('admin')")
@PreAuthorize("hasRole(@roles.USER)") where roles is a bean
de ned with @Component annotation and USER is a public eld
of the class.
hasAnyRole
@PreAuthorize("hasAnyRole(@roles.USER, 'view')")
Permit and Deny All
@PreAuthorize("permitAll()")
@PreAuthorize("denyAll()")
Anonymous and Authenticated
@PreAuthorize("isAnonymous()")
@PreAuthorize("isAuthenticated()")
Checks if the current logged in user is the same as the
username method parameter:
@PreAuthorize("#person.name == authentication.principal.use
rname")
public void doSomethingElse(Person person){}
Checks if calling a method if user can access:
@PreAuthorize("@personChecker.check(#person, authenticatio
n.principal.username)")
public void doSomething(Person person){}
@Component
public class PersonChecker {
public boolean check(Person person, String username) {
return person.getName().equals(username);
}
}
Combining expressions:
@PreAuthorize("hasAnyRole('user', 'admin') AND #user == pri
ncipal.username")
public void allowedForUser(String user) {}
Spring Cache
Quarkus provides a compatibility layer for Spring dependency
injection.
./mvnw quarkus:add-extension
-Dextensions="spring-cache"
@org.springframework.cache.annotation.Cacheable("someCache"
)
public Greeting greet(String name) {}
Quarkus provides compatibility with the following Spring Cache
annotations:
@Cacheable
@CachePut
@CacheEvict
Spring Schedule
Quarkus provides a compatibility layer for Spring Scheduled
annotation.
./mvnw quarkus:add-extension
-Dextensions="spring-scheduled"
@org.springframework.scheduling.annotation.Scheduled(cron=
"*/5 * * * * ?")
void cronJob() {
System.out.println("Cron expression hardcoded");
}
@Scheduled(fixedRate = 1000)
@Scheduled(cron = "{cron.expr}")
Resources
https://quarkus.io/guides/
https://www.youtube.com/user/lordofthejars
Authors :
@alexsotob
Java Champion and Director of DevExp at Red Hat
2.7.0.Final
Quarkus Annonation and Commands Cheat Sheet

More Related Content

PDF
PDF
PDF
Scala test
PDF
Rediscovering Spring with Spring Boot(1)
PDF
dokumen.tips_rediscovering-spring-with-spring-boot1 (1).pdf
PDF
dokumen.tips_rediscovering-spring-with-spring-boot1.pdf
PDF
Jdbc[1]
PDF
JDBC programming
Scala test
Rediscovering Spring with Spring Boot(1)
dokumen.tips_rediscovering-spring-with-spring-boot1 (1).pdf
dokumen.tips_rediscovering-spring-with-spring-boot1.pdf
Jdbc[1]
JDBC programming

Similar to Quarkus Annonation and Commands Cheat Sheet (20)

PDF
Meetup 2022 - APIs with Quarkus.pdf
PDF
Continuous Delivery with Maven, Puppet and Tomcat - ApacheCon NA 2013
PPT
比XML更好用的Java Annotation
PDF
Agile Swift
PDF
Divide and Conquer – Microservices with Node.js
PPTX
Vert.x - Reactive & Distributed [Devoxx version]
PDF
Introduction to JDBC and database access in web applications
PDF
ODP
Bring the fun back to java
PPTX
An introduction to Test Driven Development on MapReduce
PDF
Antons Kranga Building Agile Infrastructures
PPT
SMI - Introduction to Java
PDF
Kirill Rozin - Practical Wars for Automatization
PDF
Continuous Delivery: The Next Frontier
PDF
spring-tutorial
PPTX
Amazon elastic map reduce
PDF
Testing multi outputformat based mapreduce
PPTX
SCWCD : Thread safe servlets : CHAP : 8
PDF
Meetup 2022 - APIs with Quarkus.pdf
Continuous Delivery with Maven, Puppet and Tomcat - ApacheCon NA 2013
比XML更好用的Java Annotation
Agile Swift
Divide and Conquer – Microservices with Node.js
Vert.x - Reactive & Distributed [Devoxx version]
Introduction to JDBC and database access in web applications
Bring the fun back to java
An introduction to Test Driven Development on MapReduce
Antons Kranga Building Agile Infrastructures
SMI - Introduction to Java
Kirill Rozin - Practical Wars for Automatization
Continuous Delivery: The Next Frontier
spring-tutorial
Amazon elastic map reduce
Testing multi outputformat based mapreduce
SCWCD : Thread safe servlets : CHAP : 8
Ad

Recently uploaded (20)

PDF
Network Security Unit 5.pdf for BCA BBA.
PDF
Unlocking AI with Model Context Protocol (MCP)
PPTX
Cloud computing and distributed systems.
PDF
Reach Out and Touch Someone: Haptics and Empathic Computing
PDF
Peak of Data & AI Encore- AI for Metadata and Smarter Workflows
PDF
Building Integrated photovoltaic BIPV_UPV.pdf
PPTX
Digital-Transformation-Roadmap-for-Companies.pptx
PDF
The Rise and Fall of 3GPP – Time for a Sabbatical?
PPTX
Effective Security Operations Center (SOC) A Modern, Strategic, and Threat-In...
PPTX
Understanding_Digital_Forensics_Presentation.pptx
PDF
Dropbox Q2 2025 Financial Results & Investor Presentation
PDF
Architecting across the Boundaries of two Complex Domains - Healthcare & Tech...
PDF
Electronic commerce courselecture one. Pdf
PPTX
Programs and apps: productivity, graphics, security and other tools
PDF
How UI/UX Design Impacts User Retention in Mobile Apps.pdf
PDF
Optimiser vos workloads AI/ML sur Amazon EC2 et AWS Graviton
PDF
KodekX | Application Modernization Development
PPTX
VMware vSphere Foundation How to Sell Presentation-Ver1.4-2-14-2024.pptx
PDF
Blue Purple Modern Animated Computer Science Presentation.pdf.pdf
PDF
Spectral efficient network and resource selection model in 5G networks
Network Security Unit 5.pdf for BCA BBA.
Unlocking AI with Model Context Protocol (MCP)
Cloud computing and distributed systems.
Reach Out and Touch Someone: Haptics and Empathic Computing
Peak of Data & AI Encore- AI for Metadata and Smarter Workflows
Building Integrated photovoltaic BIPV_UPV.pdf
Digital-Transformation-Roadmap-for-Companies.pptx
The Rise and Fall of 3GPP – Time for a Sabbatical?
Effective Security Operations Center (SOC) A Modern, Strategic, and Threat-In...
Understanding_Digital_Forensics_Presentation.pptx
Dropbox Q2 2025 Financial Results & Investor Presentation
Architecting across the Boundaries of two Complex Domains - Healthcare & Tech...
Electronic commerce courselecture one. Pdf
Programs and apps: productivity, graphics, security and other tools
How UI/UX Design Impacts User Retention in Mobile Apps.pdf
Optimiser vos workloads AI/ML sur Amazon EC2 et AWS Graviton
KodekX | Application Modernization Development
VMware vSphere Foundation How to Sell Presentation-Ver1.4-2-14-2024.pptx
Blue Purple Modern Animated Computer Science Presentation.pdf.pdf
Spectral efficient network and resource selection model in 5G networks
Ad

Quarkus Annonation and Commands Cheat Sheet

  • 1. Quarkus Cheat-Sheet What is Quarkus? Quarkus is a Kubernetes Native Java stack tailored for GraalVM & OpenJDK HotSpot, crafted from the best of breed Java libraries and standards. Also focused on developer experience, making things just work with little to no con guration and allowing to do live coding. Cheat-sheet tested with Quarkus 2.7.0.Final. Getting Started Quarkus comes with a Maven archetype to scaffold a very simple starting project. mvn io.quarkus:quarkus-maven-plugin:2.7.0.Final:create -DprojectGroupId=org.acme -DprojectArtifactId=getting-started -DclassName="org.acme.quickstart.GreetingResource" -Dpath="/hello" This creates a simple JAX-RS resource called GreetingResource. @Path("/hello") public class GreetingResource { @GET @Produces(MediaType.TEXT_PLAIN) public String hello() { return "hello"; } } Gradle There is no way to scaffold a project in Gradle but you only need to do: plugins { id 'java' id 'io.quarkus' version '0.26.1' } repositories { mavenCentral() } dependencies { implementation enforcedPlatform('io.quarkus:quarkus-bo m:0.26.1') implementation 'io.quarkus:quarkus-resteasy' } Or in Kotlin: plugins { java } apply(plugin = "io.quarkus") repositories { mavenCentral() } dependencies { implementation(enforcedPlatform("io.quarkus:quarkus-bo m:0.26.1")) implementation("io.quarkus:quarkus-resteasy") } Packaging mvn clean package You need to distribute the -runner.jar le together with quarkus- app directory. If quarkus.package.uber-jar property is set to true, then a uber-jar is created with all dependencies bundled inside the JAR. By default, Quarkus uses fast jar packaging, if quarkus.package.type property is set to legacy-jar then Quarkus creates the old standard jar le. application.properties quarkus.package.uber-jar=true quarkus.package.type=legacy-jar To compile to native, you need to set GRAALVM_HOME environment variable and run the native pro le. mvn clean package -Pnative ./gradlew build -Dquarkus.package.type=native Possible quarkus.package.type are: jar, legacy-jar, uber-jar and native. AppCDS Automatically generate AppCDS as part of the build process set the next property: quarkus.package.create-appcds=true. To make use of it, just run java -jar -XX:SharedArchiveFile=app- cds.jsa myapp.jar. Command mode You can de ne the main CLI method to start Quarkus. There are two ways, implementing io.quarkus.runtime.QuarkusApplication interface or use the Java main method to launch Quarkus. @io.quarkus.runtime.annotations.QuarkusMain public class HelloWorldMain implements QuarkusApplication { @Override public int run(String... args) throws Exception { System.out.println("Hello World"); return 10; } } run method called when Quarkus starts, and stops when it nishes. As Java main: @QuarkusMain public class JavaMain { public static void main(String... args) { Quarkus.run(HelloWorldMain.class, args); } } Use @QuarkusMain in only one place. Use Quarkus.waitForExit() from the main thread if you want to run some logic on startup, and then run like a normal application (i.e. not exit). You can inject command line arguments by using @CommandLineArguments annotation: @CommandLineArguments String[] args; Testing Command Mode applications can be tested using the @QuarkusMainTest and @QuarkusMainIntegrationTest annotations.
  • 2. import io.quarkus.test.junit.main.Launch; import io.quarkus.test.junit.main.LaunchResult; import io.quarkus.test.junit.main.QuarkusMainLauncher; import io.quarkus.test.junit.main.QuarkusMainTest; @QuarkusMainTest public class HelloTest { @Test @Launch("World") public void testLaunchCommand(LaunchResult result) { Assertions.assertEquals("Hello World", result.getOu tput()); } @Test @Launch(value = {}, exitCode = 1) public void testLaunchCommandFailed() { } @Test public void testManualLaunch(QuarkusMainLauncher launch er) { LaunchResult result = launcher.launch("Everyone"); Assertions.assertEquals(0, result.exitCode()); Assertions.assertEquals("Hello Everyone", result.ge tOutput()); } } Picocli You can use Picocli to implement CLI applications: ./mvnw quarkus:add-extension -Dextensions="picocli" @CommandLine.Command public class HelloCommand implements Runnable { @CommandLine.Option(names = {"-n", "--name"}, descripti on = "Who will we greet?", defaultValue = "World") String name; private final GreetingService greetingService; public HelloCommand(GreetingService greetingService) { this.greetingService = greetingService; } @Override public void run() { greetingService.sayHello(name); } } All classes annotated with picocli.CommandLine.Command are registered as CDI beans. If only one class annotated with picocli.CommandLine.Command it will be used as entry point. If you want to provide your own @QuarkusMain @CommandLine.Command(name = "demo", mixinStandardHelpOption s = true) public class ExampleApp implements Runnable, QuarkusApplica tion { @Inject CommandLine.IFactory factory; @Override public void run() { } @Override public int run(String... args) throws Exception { return new CommandLine(this, factory).execute(arg s); } } Use quarkus.picocli.native-image.processing.enable to false to use the picocli-codegen annotation processor instead of build steps. You can also con gure CDI beans with PicoCLI arguments: @CommandLine.Command public class EntryCommand implements Runnable { @CommandLine.Option(names = "-c", description = "JDBC c onnection string") String connectionString; @Inject DataSource dataSource; } @ApplicationScoped class DatasourceConfiguration { @Produces @ApplicationScoped DataSource dataSource(CommandLine.ParseResult parseResu lt) { System.out.println(parseResult.matchedOption("c").g etValue().toString()); } } Extensions Quarkus comes with extensions to integrate with some libraries such as JSON-B, Camel or MicroPro le spec. To list all available extensions just run: ./mvnw quarkus:list-extensions You can use -DsearchPattern=panache to lter out all extensions except the ones matching the expression. And to register the extensions into build tool: ./mvnw quarkus:add-extension -Dextensions="" ./mvnw quarkus:remove-extension -Dextensions="" extensions property supports CSV format to register more than one extension at once. Application Lifecycle You can be noti ed when the application starts/stops by observing StartupEvent and ShutdownEvent events. @ApplicationScoped public class ApplicationLifecycle { void onStart(@Observes StartupEvent event) {} void onStop(@Observes ShutdownEvent event) {} } Quarkus supports graceful shutdown. By default there is no timeout but can be set by using the quarkus.shutdown.timeout con g property. Dev Mode ./mvnw compile quarkus:dev ./gradlew quarkusDev Endpoints are registered automatically to provide some basic debug info in dev mode: HTTP GET /quarkus/arc/beans Query Parameters: scope, beanClass, kind. HTTP GET /quarkus/arc/observers Dev Services Quarkus supports the automatic provisioning of uncon gured services in development and test mode. General con guration properties: quarkus.devservices.enabled If you want to disable all Dev Services. (default: true) quarkus.devservices.timeout Startup timeout. (default: 60S) Set DOCKER_HOST env var to a remote Docker Host to use it instead the local one. Dev UI
  • 3. Quarkus adds a Dev UI console to expose extension features. The Dev UI is available in dev mode only and accessible at the /q/dev endpoint by default. Continuous Testing Quarkus supports continuous testing, where tests run immediately after code changes have been saved. This allows you to get instant feedback on your code changes. Quarkus detects which tests cover which code, and uses this information to only run the relevant tests when code is changed. Start Quarkus in Dev Mode to run it. Also, you can start continuous testing and not dev mode by running mvn quarkus:test. quarkus.test.exclude-pattern Tests that should be excluded with continuous testing default: .*.IT[^.]+|.*IT|.*ITCase Adding Con guration Parameters To add con guration to your application, Quarkus relies on MicroPro le Con g spec. @ConfigProperty(name = "greetings.message") String message; @ConfigProperty(name = "greetings.message", defaultValue = "Hello") String messageWithDefault; @ConfigProperty(name = "greetings.message") Optional<String> optionalMessage; Properties can be set (in decreasing priority) as: System properties (-Dgreetings.message). Environment variables (GREETINGS_MESSAGE). Environment le named .env placed in the current working directory (GREETING_MESSAGE=). External con g directory under the current working directory: config/application.properties. Resources src/main/resources/application.properties. greetings.message = Hello World Array, List and Set are supported. The delimiter is comma (,) char and is the escape char. Con guration Pro les Quarkus allow you to have multiple con guration in the same le (application.properties). The syntax for this is %{profile}.config.key=value. quarkus.http.port=9090 %dev.quarkus.http.port=8181 HTTP port will be 9090, unless the 'dev' pro le is active. Default pro les are: dev: Activated when in development mode (quarkus:dev). test: Activated when running tests. prod: The default pro le when not running in development or test mode You can create custom pro le names by enabling the pro le either setting quarkus.profile system property or QUARKUS_PROFILE environment variable. quarkus.http.port=9090 %staging.quarkus.http.port=9999 And enable it quarkus.profile=staging. To get the active pro le programmatically use io.quarkus.runtime.configuration.ProfileManager.getActiveProfile(). You can also set it in the build tool: <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>${surefire-plugin.version}</version> <configuration> <systemPropertyVariables> <quarkus.test.profile>foo</quarkus.test.profile> <buildDirectory>${project.build.directory} </buildDirectory> </systemPropertyVariables> </configuration> Same for maven-failsafe-plugin. test { useJUnitPlatform() systemProperty "quarkus.test.profile", "foo" } Special properties are set in prod mode: quarkus.application.version and quarkus.application.name to get them available at runtime. @ConfigProperty(name = "quarkus.application.name") String applicationName; Additional locations You can use smallrye.config.locations property to set additional con guration les. smallrye.config.locations=config.properties or java -jar -Dsmallrye.config.locations=config.properties You can embed con guration les inside a dependency by adding META-INF/microprofile.properties inside the JAR. When dependency is added to the application, con guration properties are merged with current con guration. @Con gProperties As an alternative to injecting multiple related con guration values, you can also use the @io.quarkus.arc.config.ConfigProperties annotation to group properties. @ConfigProperties(prefix = "greeting", namingStrategy=Namin gStrategy.KEBAB_CASE) public class GreetingConfiguration { private String message; // getter/setter } This class maps greeting.message property de ned in application.properties. You can inject this class by using CDI @Inject GreetingConfiguration greeting;. @IfBuildProfile, @UnlessBuildProfile, @IfBuildProperty and @UnlessBuildProperty annotations are used to de ne when con guration properties are valid. @UnlessBuildProfile("test") @ConfigProperties public class ServiceConfiguration { public String user; public String password; } Also you can use an interface approach: @ConfigProperties(prefix = "greeting", namingStrategy=Namin gStrategy.KEBAB_CASE) public interface GreetingConfiguration { @ConfigProperty(name = "message") String message(); String getSuffix();
  • 4. If property does not follow getter/setter naming convention you need to use org.eclipse.microprofile.config.inject.ConfigProperty to set it. Nested objects are also supporte: @ConfigProperties(prefix = "greeting", namingStrategy=Namin gStrategy.KEBAB_CASE) public class GreetingConfiguration { public String message; public HiddenConfig hidden; public static class HiddenConfig { public List<String> recipients; } } And an application.properties mapping previous class: greeting.message = hello greeting.hidden.recipients=Jane,John Bean Validation is also supported so properties are validated at startup time, for example @Size(min = 20) public String message;. prefix attribute is not mandatory. If not provided, attribute is determined by class name (ie GreeetingConfiguration is translated to greeting or GreetingExtraConfiguration to greeting-extra). The su x of the class is always removed. Naming strategy can be changed with property namingStrategy. KEBAB_CASE (whatever.foo-bar) or VERBATIM (whatever.fooBar). @io.quarkus.arc.config.ConfigIgnore annotation can be used to ignore the injection of con guration elements. @ConfigIgnore public Integer ignored; YAML Con g YAML con guration is also supported. The con guration le is called application.yaml and you need to register a dependency to enable its support: pom.xml <dependency> <groupId>io.quarkus</groupId> <artifactId>quarkus-config-yaml</artifactId> </dependency> quarkus: datasource: url: jdbc:postgresql://localhost:5432/some-database driver: org.postgresql.Driver Or with pro les: "%dev": quarkus: datasource: url: jdbc:postgresql://localhost:5432/some-database driver: org.postgresql.Driver In case of subkeys ~ is used to refer to the unpre xed part. quarkus: http: cors: ~: true methods: GET,PUT,POST Is equivalent to: quarkus.http.cors=true quarkus.http.cors.methods=GET,PUT,POST Custom Loader You can implement your own ConfigSource to load con guration from different places than the default ones provided by Quarkus. For example, database, custom XML, REST Endpoints, … You need to create a new class and implement ConfigSource interface: package com.acme.config; public class InMemoryConfig implements ConfigSource { private Map<String, String> prop = new HashMap<>(); public InMemoryConfig() { // Init properties } @Override public int getOrdinal() { // The highest ordinal takes precedence return 900; } @Override public Map<String, String> getProperties() { return prop; } @Override public String getValue(String propertyName) { return prop.get(propertyName); } @Override public String getName() { return "MemoryConfigSource"; } } Then you need to register the ConfigSource as Java service. Create a le with the following content: /META-INF/services/org.eclipse.microprofile.config.spi.ConfigSource com.acme.config.InMemoryConfig Custom Converters You can implement your own conversion types from String. Implement org.eclipse.microprofile.config.spi.Converter interface: @Priority(DEFAULT_QUARKUS_CONVERTER_PRIORITY + 100) public class CustomInstantConverter implements Converter<Instant> { @Override public Instant convert(String value) { if ("now".equals(value.trim())) { return Instant.now(); } return Instant.parse(value); } } @Priority annotation is used to override the default InstantConverter.
  • 5. Then you need to register the Converter as Java service. Create a le with the following content: /META-INF/services/org.eclipse.microprofile.config.spi.Converter com.acme.config.CustomInstantConverter Undertow Properties Possible parameters with pre x quarkus.servlet: context-path The context path to serve all Servlet context from. (default: /) default-charset The default charset to use for reading and writing requests. (default: UTF-8) Injection Quarkus is based on CDI 2.0 to implement injection of code. It is not fully supported and only a subset of the speci cation is implemented. @ApplicationScoped public class GreetingService { public String message(String message) { return message.toUpperCase(); } } Scope annotation is mandatory to make the bean discoverable. @Inject GreetingService greetingService; Quarkus is designed with Substrate VM in mind. For this reason, we encourage you to use package-private scope instead of private. Produces You can also create a factory of an object by using @javax.enterprise.inject.Produces annotation. @Produces @ApplicationScoped Message message() { Message m = new Message(); m.setMsn("Hello"); return m; } @Inject Message msg; Quali ers You can use quali ers to return different implementations of the same interface or to customize the con guration of the bean. @Qualifier @Retention(RUNTIME) @Target({TYPE, METHOD, FIELD, PARAMETER}) public @interface Quote { @Nonbinding String value(); } @Produces @Quote("") Message message(InjectionPoint msg) { Message m = new Message(); m.setMsn( msg.getAnnotated() .getAnnotation(Quote.class) .value() ); return m; } @Inject @Quote("Aloha Beach") Message message; Quarkus breaks the CDI spec by allowing you to inject quali ed beans without using @Inject annotation. @Quote("Aloha Beach") Message message; Quarkus breaks the CDI spec by skipping the @Produces annotation completely if the producer method is annotated with a scope annotation, a stereotype or a quali er. @Quote("") Message message(InjectionPoint msg) { } @Quote("Aloha Beach") Message message; @LookupIfProperty indicates that a bean should only be obtained if a runtime con guration property matches the provided value. @LookupUnlessProperty, on the other hand, indicates that a bean should only be obtained if a runtime con guration property does not match the provided value. @LookupIfProperty(name = "service.foo.enabled", stringValue = "true") @ApplicationScoped class ServiceFoo implements Service { public String name() { return "foo"; } } Alternatives It is also possible to select alternatives for an application using application.properties. quarkus.arc.selected-alternatives=org.acme.Foo,org.acme.*,B ar Beans by Quarkus Pro le Using @io.quarkus.arc.profile.IfBuildProfile and @io.quarkus.arc.profile.UnlessBuildProfile annotations, you can conditionally enable a bean. @Dependent public class TracerConfiguration { @Produces @IfBuildProfile("prod") public Tracer realTracer(Reporter reporter, Configurati on configuration) { return new RealTracer(reporter, configuration); } @Produces @DefaultBean public Tracer noopTracer() { return new NoopTracer(); } } Using @io.quarkus.arc.profile.IfBuildProperty annotation, you can conditionally enable a bean. @io.quarkus.arc.DefaultBean sets the default bean. @Dependent public class TracerConfiguration { @Produces @IfBuildProperty(name = "some.tracer.enabled", stringVa lue = "true") public Tracer realTracer(Reporter reporter, Configurati on configuration) {} @Produces @DefaultBean public Tracer noopTracer() {} }
  • 6. Properties set at runtime have absolutely no effect on the bean resolution using @IfBuildProperty. Container-managed Concurrency Quarkus provides @io.quarkus.arc.Lock and a built-in interceptor for concurrency control. @Lock @ApplicationScoped class SharedService { void addAmount(BigDecimal amout) { } @Lock(value = Lock.Type.READ, time = 1, unit = TimeUni t.SECONDS) BigDecimal getAmount() { } } By default the class is in write mode (so no concurrent calls allowed) except when lock type is READ where the method can be called concurrently if no write operation in process. JSON Marshalling/Unmarshalling To work with JSON-B you need to add a dependency: ./mvnw quarkus:add-extension -Dextensions="io.quarkus:quarkus-resteasy-jsonb" Any POJO is marshaled/unmarshalled automatically. public class Sauce { private String name; private long scovilleHeatUnits; // getter/setters } JSON equivalent: { "name":"Blair's Ultra Death", "scovilleHeatUnits": 1100000 } In a POST endpoint example: @POST @Consumes(MediaType.APPLICATION_JSON) public Response create(Sauce sauce) { // Create Sauce return Response.created(URI.create(sauce.getId())) .build(); } To provide custom JsonBCon g object: @Dependent JsonbConfig jsonConfig(Instance<JsonbConfigCustomizer> cust omizers) { JsonbConfig config = myJsonbConfig(); // Custom `JsonbC onfig` for (JsonbConfigCustomizer customizer : customizers) { customizer.customize(config); } return config; } To work with Jackson you need to add: ./mvnw quarkus:add-extension -Dextensions="quarkus-resteasy-jackson" If you don’t want to use the default ObjectMapper you can customize it by: @ApplicationScoped public class CustomObjectMapperConfig { @Singleton @Produces public ObjectMapper objectMapper(Instance<ObjectMapperC ustomizer> customizers) { ObjectMapper objectMapper = new ObjectMapper(); // perform configuration for (ObjectMapperCustomizer customizer : customizer s) { customizer.customize(mapper); } return objectMapper; } } Default media type in Quarkus RestEasy is JSON. XML Marshalling/Unmarshalling To work with JAX-B you need to add a dependency: ./mvnw quarkus:add-extension -Dextensions="quarkus-resteasy-jaxb" Then annotated POJOs are converted to XML. @XmlRootElement public class Message { } @GET @Produces(MediaType.APPLICATION_XML) public Message hello() { return message; } JAXP To work with JAX-P you need to add a dependency: ./mvnw quarkus:add-extension -Dextensions="jaxp" final DocumentBuilder dBuilder = DocumentBuilderFactory.new Instance().newDocumentBuilder(); final Document doc = dBuilder.parse(in); return doc.getDocumentElement().getTextContent(); Validator Quarkus uses Hibernate Validator to validate input/output of REST services and business services using Bean validation spec. ./mvnw quarkus:add-extension -Dextensions="io.quarkus:quarkus-hibernate-validator" Annotate POJO objects with validator annotations such as: @NotNull, @Digits, @NotBlank, @Min, @Max, … public class Sauce { @NotBlank(message = "Name may not be blank") private String name; @Min(0) private long scovilleHeatUnits; // getter/setters } To validate an object use @Valid annotation: public Response create(@Valid Sauce sauce) {}
  • 7. If a validation error is triggered, a violation report is generated and serialized as JSON. If you want to manipulate the output, you need to catch in the code the ConstraintViolationException exception. Create Your Custom Constraints First you need to create the custom annotation: @Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE }) @Retention(RUNTIME) @Documented @Constraint(validatedBy = { NotExpiredValidator.class}) public @interface NotExpired { String message() default "Sauce must not be expired"; Class<?>[] groups() default { }; Class<? extends Payload>[] payload() default { }; } You need to implement the validator logic in a class that implements ConstraintValidator. public class NotExpiredValidator implements ConstraintValidator<NotExpired, LocalDate> { @Override public boolean isValid(LocalDate value, ConstraintValidatorContext ctx) { if ( value == null ) return true; LocalDate today = LocalDate.now(); return ChronoUnit.YEARS.between(today, value) > 0; } } And use it normally: @NotExpired @JsonbDateFormat(value = "yyyy-MM-dd") private LocalDate expired; Manual Validation You can call the validation process manually instead of relaying to @Valid by injecting Validator class. @Inject Validator validator; And use it: Set<ConstraintViolation<Sauce>> violations = validator.validate(sauce); Localization You can con gure the based locale for validation messages. quarkus.default-locale=ca-ES # Supported locales resolved by Accept-Language quarkus.locales=en-US,es-ES,fr-FR, ca_ES ValidationMessages_ca_ES.properties pattern.message=No conforme al patro @Pattern(regexp = "A.*", message = "{pattern.message}") private String name; Bean Validation can be con gured . The pre x is: quarkus.hibernate-validator. fail-fast When fail fast is enabled the validation will stop on the rst constraint violation detected. (default: false) method-validation.allow-overriding-parameter-constraints De ne whether overriding methods that override constraints should throw an exception. (default: false). method-validation.allow-parameter-constraints-on-parallel-methods De ne whether parallel methods that de ne constraints should throw an exception. (default: false). method-validation.allow-multiple-cascaded-validation-on-return- values De ne whether more than one constraint on a return value may be marked for cascading validation are allowed. (default: false). Logging You can con gure how Quarkus logs: quarkus.log.console.enable=true quarkus.log.console.level=DEBUG quarkus.log.console.color=false quarkus.log.category."com.lordofthejars".level=DEBUG Pre x is quarkus.log. category."<category-name>".level Minimum level category (default: INFO) level Default minimum level (default: INFO) console.enabled Console logging enabled (default: true) console.format Format pattern to use for logging. Default value: %d{yyyy-MM-dd HH:mm:ss,SSS} %-5p [%c{3.}] (%t) %s%e%n console.level Minimum log level (default: INFO) console.color Allow color rendering (default: true) console.stderr If console logging should go to System#err instead of System#out (default: false) file.enable File logging enabled (default: false) file.format Format pattern to use for logging. Default value: %d{yyyy-MM-dd HH:mm:ss,SSS} %h %N[%i] %-5p [%c{3.}] (%t) %s%e%n file.level Minimum log level (default: ALL) file.path The path to log le (default: quarkus.log) file.rotation.max-file-size The maximum le size of the log le file.rotation.max-backup-index The maximum number of backups to keep (default: 1) file.rotation.file-suffix Rotating log le su x. file.rotation.rotate-on-boot Indicates rotate logs at bootup (default: true) file.async Log asynchronously (default: false) file.async.queue-length The queue length to use before ushing writing (default: 512) file.async.overflow Action when queue is full (default: BLOCK) syslog.enable syslog logging is enabled (default: false) syslog.format The format pattern to use for logging to syslog. Default value: %d{yyyy-MM-dd HH:mm:ss,SSS} %h %N[%i] %-5p [%c{3.}] (%t) %s%e%n syslog.level The minimum log level to write to syslog (default: ALL)
  • 8. syslog.endpoint The IP address and port of the syslog server (default: localhost:514) syslog.app-name The app name used when formatting the message in RFC5424 format (default: current process name) syslog.hostname The name of the host the messages are being sent from (default: current hostname) syslog.facility Priority of the message as de ned by RFC-5424 and RFC-3164 (default: USER_LEVEL) syslog.syslog-type The syslog type of format message (default: RFC5424) syslog.protocol Protocol used (default: TCP) syslog.use-counting-framing Message pre xed with the size of the message (default false) syslog.truncate Message should be truncated (default: true) syslog.block-on-reconnect Block when attempting to reconnect (default: true) syslog.async Log asynchronously (default: false) syslog.async.queue-length The queue length to use before ushing writing (default: 512) syslog.async.overflow Action when queue is full (default: BLOCK) You can inject logger instance: import org.jboss.logging.Logger; import io.quarkus.arc.log.LoggerName; @Inject Logger log; @LoggerName("foo") Logger fooLog; public void ping() { log.info("Simple!"); } Gelf ouput You can con gure the output to be in GELF format instead of plain text. ./mvnw quarkus:add-extension -Dextensions="quarkus-logging-gelf" handler.gelf.enabled Enable GELF logging handler (default: false) handler.gelf.host Hostname/IP of Logstash/Graylof. Prepend tcp: for using TCP protocol. (default: udp:localhost) handler.gelf.port The port. (default: 12201) handler.gelf.version GELF version. (default: 1.1) handler.gelf.extract-stack-trace Post Stack-Trace to StackTrace eld. (default: true) handler.gelf.stack-trace-throwable-reference Gets the cause level to stack trace. 0 is fulls tack trace. (default: 0) handler.gelf.filter-stack-trace Stack-Trace ltering. (default: false) handler.gelf.timestamp-pattern Java Date pattern. (default: yyyy-MM-dd HH:mm:ss,SSS) handler.gelf.level Log level java.util.logging.Level. (default: ALL) handler.gelf.facility Name of the facility. (default: jboss-logmanage) handler.gelf.additional-field.<field>.<subfield> Post additional elds. quarkus.log.handler.gelf.additional- field.field1.type=String handler.gelf.include-full-mdc Include all elds from the MDC. handler.gelf.maximum-message-size Maximum message size (in bytes). (default: 8192) handler.gelf.include-log-message-parameters Include message parameters from the log event. (default: true) handler.gelf.include-location Include source code location. (default: true) JSON output You can con gure the output to be in JSON format instead of plain text. ./mvnw quarkus:add-extension -Dextensions="quarkus-logging-json" And the con guration values are pre x with quarkus.log: json JSON logging is enabled (default: true). json.pretty-print JSON output is "pretty-printed" (default: false) json.date-format Specify the date format to use (default: the default format) json.record-delimiter Record delimiter to add (default: no delimiter) json.zone-id The time zone ID json.exception-output-type The exception output type: detailed, formatted, detailed-and- formatted (default: detailed) json.print-details Detailed caller information should be logged (default: false) Rest Client Quarkus implements MicroPro le Rest Client spec: ./mvnw quarkus:add-extension -Dextensions="quarkus-rest-client" To get content from http://worldclockapi.com/api/json/cet/now you need to create a service interface: @Path("/api") @RegisterRestClient public interface WorldClockService { @GET @Path("/json/cet/now") @Produces(MediaType.APPLICATION_JSON) WorldClock getNow(); @GET @Path("/json/{where}/now") @Produces(MediaType.APPLICATION_JSON) WorldClock getSauce(@BeanParam WorldClockOptions worldClockOptions); }
  • 9. public class WorldClockOptions { @HeaderParam("Authorization") String auth; @PathParam("where") String where; } And con gure the hostname at application.properties: org.acme.quickstart.WorldClockService/mp-rest/url= http://worldclockapi.com Injecting the client: @RestClient WorldClockService worldClockService; If invokation happens within JAX-RS, you can propagate headers from incoming to outgoing by using next property. org.eclipse.microprofile.rest.client.propagateHeaders= Authorization,MyCustomHeader You can still use the JAX-RS client without any problem ClientBuilder.newClient().target(…) Adding headers You can customize the headers passed by implementing MicroPro le ClientHeadersFactory annotation: @RegisterForReflection public class BaggageHeadersFactory implements ClientHeadersFactory { @Override public MultivaluedMap<String, String> update( MultivaluedMap<String, String> incomingHeaders, MultivaluedMap<String, String> outgoingHeaders) {} } And registering it in the client using RegisterClientHeaders annotation. @RegisterClientHeaders(BaggageHeadersFactory.class) @RegisterRestClient public interface WorldClockService {} Or statically set: @GET @ClientHeaderParam(name="X-Log-Level", value="ERROR") Response getNow(); Asynchronous A method on client interface can return a CompletionStage class to be executed asynchronously. @GET @Path("/json/cet/now") @Produces(MediaType.APPLICATION_JSON) CompletionStage<WorldClock> getNow(); Reactive Rest Client also integrates with reactive library named Mutiny. To start using it you need to add the quarkus-rest-client-mutiny. After that, a methodon a client interface can return a io.smallrye.mutiny.Uni instance. @GET @Path("/json/cet/now") @Produces(MediaType.APPLICATION_JSON) Uni<WorldClock> getNow(); A RESTEasy Reactive-based REST Client extension. You only need to replace the quarkus-rest-client to quarkus-rest-client-reactive. Multipart It is really easy to send multipart form-data with Rest Client. <dependency> <groupId>org.jboss.resteasy</groupId> <artifactId>resteasy-multipart-provider</artifactId> </dependency> The model object: import java.io.InputStream; import javax.ws.rs.FormParam; import javax.ws.rs.core.MediaType; import org.jboss.resteasy.annotations.providers.multipart.Part Type; public class MultipartBody { @FormParam("file") @PartType(MediaType.APPLICATION_OCTET_STREAM) private InputStream file; @FormParam("fileName") @PartType(MediaType.TEXT_PLAIN) private String name; // getter/setters } And the Rest client interface: import org.jboss.resteasy.annotations.providers.multipart.Mult ipartForm; @Path("/echo") @RegisterRestClient public interface MultipartService { @POST @Consumes(MediaType.MULTIPART_FORM_DATA) @Produces(MediaType.TEXT_PLAIN) String sendMultipartData(@MultipartForm MultipartBody data); } SSL You can con gure Rest Client key stores. org.acme.quickstart.WorldClockService/mp-rest/trustStore= classpath:/store.jks org.acme.quickstart.WorldClockService/mp-rest/trustStorePas sword= supersecret Possible con guration properties: %s/mp-rest/trustStore Trust store location de ned with classpath: or file: pre x. %s/mp-rest/trustStorePassword Trust store password.
  • 10. %s/mp-rest/trustStoreType Trust store type (default: JKS) %s/mp-rest/hostnameVerifier Custom hostname veri er class name. To disable SSL veri cation you can use io.quarkus.restclient.NoopHostnameVerifier. %s/mp-rest/keyStore Key store location de ned with classpath: or file: pre x. %s/mp-rest/keyStorePassword Key store password. %s/mp-rest/keyStoreType Key store type (default: JKS) Timeout You can de ne the timeout of the Rest Client: org.acme.quickstart.WorldClockService/mp-rest/connectTimeou t= 1000 org.acme.quickstart.WorldClockService/mp-rest/readTimeout= 2000 Instantiate client programmatically MovieReviewService reviewSvc = RestClientBuilder.newBuilder () .baseUri(apiUri) .build(WorldClockService.class); Testing Quarkus archetype adds test dependencies with JUnit 5 and Rest- Assured library to test REST endpoints. @QuarkusTest public class GreetingResourceTest { @Test public void testHelloEndpoint() { given() .when().get("/hello") .then() .statusCode(200) .body(is("hello")); } } Test port can be set in quarkus.http.test-port property. Timeout can be set in quarkus.http.test-timeout property. You can also inject the URL where Quarkus is started: @TestHTTPResource("index.html") URL url; @TestHTTPEndpoint(GreetingResource.class) @TestHTTPResource URL url; @QuarkusTest @TestHTTPEndpoint(GreetingResource.class) public class GreetingResourceTest { @Test public void testHelloEndpoint() { given() .when().get() .then() .statusCode(200) .body(is("hello")); } } Root path is calculated automatically, not necessary to explicitly set. If you want any changes made to be rolled back at the end ofthe test you can use the io.quarkus.test.TestTransaction annotation. QuarkusTestPro le You can de ne for each Test class a different con guration options. This implies that the Quarkus service is restarted. public class MyProfile implements io.quarkus.test.junit.Qua rkusTestProfile { @Override public Map<String, String> getConfigOverrides() { return Map.of("greetings.message", "This is a Test" ); } @Override public String getConfigProfile() { return "my-test-profile"; } @Override public Set<String> tags() { return Collections.singleton("test1"); } } @QuarkusTest @TestProfile(MyProfile.class) public class MyTestClass { } quarkus.test.profile.tags property can be set to limit test execution of test pro les. If not set all tests are executed. quarkus.test.profile.tags=test1 Quarkus Test Resource You can execute some logic before the rst test run (start) and execute some logic at the end of the test suite (stop). You need to create a class implementing QuarkusTestResourceLifecycleManager interface and register it in the test via @QuarkusTestResource annotation. public class MyCustomTestResource implements QuarkusTestResourceLifecycleManager { @Override public Map<String, String> start() { // return system properties that // should be set for the running test return Collections.emptyMap(); } @Override public void stop() { } // optional @Override public void inject(Object testInstance) { } // optional @Override public int order() { return 0; } // optional @Override public void setContext(Context context) { } @Override public void inject(TestInjector testInjector) { testInjector.injectIntoFields(wireMockServer, new TestInjector.AnnotatedAndMatchesType(Inject WireMock.class, WireMockServer.class)); } } public class MyTest { @InjectWireMock WireMockServer wireMockServer; } Returning new system properties implies running parallel tests in different JVMs.
  • 11. And the usage: @QuarkusTestResource(MyCustomTestResource.class) public class MyTest { } When using multiple QuarkusTestResource you can set parallel attribute to true to start them concurrently. Testing Callbacks You can enrich all your @QuarkusTest classes by implementing the following callback interfaces: io.quarkus.test.junit.callback.QuarkusTestBeforeClassCallback io.quarkus.test.junit.callback.QuarkusTestAfterConstructCall back io.quarkus.test.junit.callback.QuarkusTestBeforeEachCallback io.quarkus.test.junit.callback.QuarkusTestAfterEachCallback public class SimpleAnnotationCheckerBeforeClassCallback imp lements QuarkusTestBeforeClassCallback { @Override public void beforeClass(Class<?> testClass) { } } And needs to be registered as Java SPI: META- INF/services/io.quarkus.test.junit.callback.QuarkusTestBeforeClassCallback io.quarkus.it.main.SimpleAnnotationCheckerBeforeClassCallba ck Mocking If you need to provide an alternative implementation of a service (for testing purposes) you can do it by using CDI @Alternative annotation using it in the test service placed at src/test/java: @Alternative @Priority(1) @ApplicationScoped public class MockExternalService extends ExternalService {} This does not work when using native image testing. A stereotype annotation io.quarkus.test.Mock is provided declaring @Alternative, @Priority(1) and @Dependent. Mockito Instead of creating stubs, you can also create mocks of your services with mockito Add the following dependency io.quarkus:quarkus-junit5-mockito: @InjectMock GreetingService greetingService; @BeforeEach public void setup() { Mockito.when(greetingService.greet()).thenReturn("Hi"); } @Path("/hello") public class ExampleResource { @Inject GreetingService greetingService; } Mock is automatically injected and only valid for the de ned test class. @InjectMock has convertScopes parameter that if true, then Quarkus will change the scope of the target from Singleton bean to ApplicationScoped to make the mockable. Also spy is supported: @InjectSpy GreetingService greetingService; Mockito.verify(greetingService, Mockito.times(1)).greet(); REST Client To Mock REST Client, you need to de ne the interface with @ApplicationScope: @ApplicationScoped @RegisterRestClient public interface GreetingService { } @InjectMock @RestClient GreetingService greetingService; Mockito.when(greetingService.hello()).thenReturn("hello fro m mockito"); Interceptors Tests are actually full CDI beans, so you can apply CDI interceptors: @QuarkusTest @Stereotype @Transactional @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface TransactionalQuarkusTest { } @TransactionalQuarkusTest public class TestStereotypeTestCase {} Decorator Quarkus also supports CDI Decorators: @Priority(10) @Decorator public class LargeTxAccount implements Account { @Inject @Any @Delegate Account delegate; @Inject LogService logService; void withdraw(BigDecimal amount) { delegate.withdraw(amount); if (amount.compareTo(1000) > 0) { logService.logWithdrawal(delegate, amount); } } } Test Coverage Due the nature of Quarkus to calculate correctly the coverage information with JaCoCo, you might need o ine instrumentation. ./mvnw quarkus:add-extension -Dextensions="quarkus-jacoco " Possible con guration parameters pre xed quarkus.jacoco: data-file The jacoco data le. (default: jacoco-quarkus.exec) report If Quarkus should generate the Jacoco report. (default: true) output-encoding Encoding of the generated reports. (default: UTF-8) title Name of the root node HTML report pages.
  • 12. footer Footer text used in HTML report pages. source-encoding Encoding of the source les. (default: UTF-8) includes A list of class les to include in the report. (default: **) excludes A list of class les to exclude from the report. report-location The location of the report les. (default: jacoco-report) Native Testing To test native executables annotate the test with @NativeImageTest. Quarkus Integration Tests @QuarkusIntegrationTest should be used to launch and test the artifact produced by the Quarkus build. If the result of a Quarkus build is a JAR then the app is launched as java -jar, if native is launched as ./application, if container image is created (JiB, Docker extensions) is launched as docker run. You can connect to already running application by using the following properties: quarkus.http.test-host=1.2.3.4 quarkus.http.test-port=4321 Persistence Quarkus works with JPA(Hibernate) as persistence solution. But also provides an Active Record pattern implementation under Panache project. To use database access you need to add Quarkus JDBC drivers instead of the original ones. At this time Apache Derby, H2, MariaDB, MySQL, MSSQL and PostgreSQL drivers are supported. ./mvnw quarkus:add-extension -Dextensions="io.quarkus:quarkus-hibernate-orm-panache, io.quarkus:quarkus-jdbc-mariadb" @Entity public class Developer extends PanacheEntity { // id field is implicit public String name; } And con guration in src/main/resources/application.properties: quarkus.datasource.jdbc.url=jdbc:mariadb://localhost:3306/m ydb quarkus.datasource.db-kind=mariadb quarkus.datasource.username=developer quarkus.datasource.password=developer quarkus.hibernate-orm.database.generation=update List of datasource parameters. quarkus.datasource as pre x is skipped in the next table. db-kind Built-in datasource kinds so the JDBC driver is resolved automatically. Possible values: derby, h2, mariadb, mssql, mysql, postgresql, db2. username Username to access. password Password to access. driver JDBC Driver class. It is not necessary to set if db-kind used. credentials-provider Sets a custom credential provider name. credentials-provider-name It is the @Named value of the credentials provider bean. Not necessary if only one implementation. jdbc.url The datasource URL. jdbc.min-size The datasource pool minimum size. (default: 0) jdbc.max-size The datasource pool maximum size. (default: 20) jdbc.initial-size The initial size of the pool. jdbc.background-validation-interval The interval at which we validate idle connections in the background. (default: 2M) jdbc.acquisition-timeout The timeout before cancelling the acquisition of a new connection. (default: 5) jdbc.leak-detection-interval The interval at which we check for connection leaks. jdbc.idle-removal-interval The interval at which we try to remove idle connections. (default: 5M) jdbc.max-lifetime The max lifetime of a connection. jdbc.transaction-isolation-level The transaction isolation level. Possible values: UNDEFINED, NONE, READ_UNCOMMITTED, READ_COMMITTED, REPEATABLE_READ, SERIALIZABLE. jdbc.detect-statement-leaks Warn when a connection is returned to the pool without the application having closed all open statements. (default: true) jdbc.new-connection-sql Query executed when rst using a connection. jdbc.validation-query-sql Query executed to validate a connection. jdbc.pooling-enabled Disable pooling to prevent reuse of Connections. (default: true) jdbc.enable-metrics Enable datasource metrics collection when using quarkus- smallrye-metrics extension. jdbc.additional-jdbc-properties.<extraProperty> Unspeci ed properties to be passed to the JDBC driver when creating new connections. Hibernate con guration properties. Pre x quarkus.hibernate-orm is skipped.
  • 13. dialect Class name of the Hibernate ORM dialect. dialect.storage-engine The storage engine when the dialect supports multiple storage engines. sql-load-script Name of the le containing the SQL statements to execute when starts. no-file force Hibernate to skip SQL import. (default: import.sql) batch-fetch-size The size of the batches. (default: -1 disabled) maxFetchDepth The maximum depth of outer join fetch tree for single-ended associations. multitenant De nes the method for multi-tenancy. Possible values: DATABASE, NONE, SCHEMA. (default: NONE) multitenant-schema-datasource De nes the name of the data source to use in case of SCHEMA approach. metadata-builder-contributor Class name of a custom org.hibernate.boot.spi.MetadataBuilderContributor implementation. query.query-plan-cache-max-size The maximum size of the query plan cache. query.default-null-ordering Default precedence of null values in ORDER BY. Possible values: none, first, last. (default: none) database.generation Database schema is generation. Possible values: none, create, drop-and-create, drop, update. (default: none) database.generation.halt-on-error Stop on the rst error when applying the schema. (default: false) database.generation.create-schemas Hibernate ORM should create the schemas automatically (for databases supporting them). database.default-catalog Default catalog. database.default-schema Default Schema. database.charset Charset. scripts.generation Select whether the database schema DDL les are generated or not. Possible values: none, create, drop-and-create, drop, update. (default: none) scripts.generation.create-target Filename or URL where the database create DDL le should be generated. scripts.generation.drop-target Filename or URL where the database drop DDL le should be generated. jdbc.timezone Time Zone JDBC driver. jdbc.statement-fetch-size Number of rows fetched at a time. jdbc.statement-batch-size Number of updates sent at a time. log.sql Show SQL logs (default: false) log.jdbc-warnings statistics Enable statiscs collection. (default: false) physical-naming-strategy Class name of the Hibernate PhysicalNamingStrategy implementation. globally-quoted-identifiers Should quote all identi ers. (default: false) metrics-enabled Metrics published with smallrye-metrics extension (default: false) second-level-caching-enabled Enable/Disable 2nd level cache. (default: true) Database operations: // Insert Developer developer = new Developer(); developer.name = "Alex"; developer.persist(); // Find All Developer.findAll().list(); // Hibernate Filters Person.findAll().filter("Person.hasName", Parameters.with( "name", "Alex")); // Find By Query Developer.find("name", "Alex").firstResult(); // Delete Developer developer = new Developer(); developer.id = 1; developer.delete(); Person.deleteById(id); // Delete By Query long numberOfDeleted = Developer.delete("name", "Alex"); Remember to annotate methods with @Transactional annotation to make changes persisted in the database. If queries start with the keyword from then they are treated as HQL query, if not then next short form is supported: order by which expands to from EntityName order by … <columnName> which expands to from EntityName where <columnName>=? <query> which is expanded to from EntityName where <query> Static Methods findById: Object Returns object or null if not found. Overloaded version with LockModeType is provided. findByIdOptional: Optional<Object> Returns object or java.util.Optional. find: String, [Object…, Map<String, Object>, Parameters] Lists of entities meeting given query with parameters set. Returning a PanacheQuery. find: String, Sort, [Object…, Map<String, Object>, Parameters] Lists of entities meeting given query with parameters set sorted by Sort attribute/s. Returning a PanacheQuery. findAll Finds all entities. Returning a PanacheQuery. findAll: Sort Finds all entities sorted by Sort attribute/s. Returning a PanacheQuery.
  • 14. list: String, [Object…, Map<String, Object>, Parameters] Lists of entities meeting given query with parameters set. Returning a List. list: String, Sort, [Object…, Map<String, Object>, Parameters] Lists of entities meeting given query with parameters set sorted by Sort attribute/s. Returning a List. listAll Finds all entities. Returning a List. listAll: Sort Finds all entities sorted by Sort attribute/s. Returning a List. stream: String, [Object…, Map<String, Object>, Parameters] java.util.stream.Stream of entities meeting given query with parameters set. stream: String, Sort, [Object…, Map<String, Object>, Parameters] java.util.stream.Stream of entities meeting given query with parameters set sorted by Sort attribute/s. streamAll java.util.stream.Stream of all entities. streamAll: Sort java.util.stream.Stream of all entities sorted by Sort attribute/s. count Number of entities. count: String, [Object…, Map<String, Object>, Parameters] Number of entities meeting given query with parameters set. Enables a Hibernate lter during fetching of results for this query. deleteAll Number of deleted entities. delete: String, [Object…, Map<String, Object>, Parameters] Number of deleted entities meeting given query with parameters set. deleteById: boolean, [Object] Delete by id. Returns if deleted or not. persist: [Iterable, Steram, Object…] Persist object. In case of using streams, remember to close them or use a try/catch block: try (Stream<Person> persons = Person.streamAll()). find methods de nes a withLock(LockModeType) to de ne the lock type and withHint(QueryHints.HINT_CACHEABLE, "true") to de ne hints. Named Queries @Entity @NamedQuery(name = "Person.getByName", query = "from Person where name = :name") public class Person extends PanacheEntity { public static Person findByName(String name){ return find("#Person.getByName", name).firstResult (); } } Pagination PanacheQuery<Person> livingPersons = Person .find("status", Status.Alive); livingPersons.page(Page.ofSize(25)); // get the first page List<Person> firstPage = livingPersons.list(); // get the second page List<Person> secondPage = livingPersons.nextPage().list(); Range PanacheQuery<Person> livingPersons = Person .find("status", Status.Alive); List<Person> secondRange = livingPersons.range(25, 49).list (); You cannot mix pagination and range. If entities are de ned in external JAR, you need to enable in these projects the Jandex plugin in project. <plugin> <groupId>org.jboss.jandex</groupId> <artifactId>jandex-maven-plugin</artifactId> <version>1.0.3</version> <executions> <execution> <id>make-index</id> <goals> <goal>jandex</goal> </goals> </execution> </executions> <dependencies> <dependency> <groupId>org.jboss</groupId> <artifactId>jandex</artifactId> <version>2.1.1.Final</version> </dependency> </dependencies> </plugin> Panache includes an annotation processor that enhance your entities If you disable annotation processors you might need to create a marker le on Panache archives at META-INF/panache- archive.marker manually. Testing To mock using active record pattern: <dependency> <groupId>io.quarkus</groupId> <artifactId>quarkus-panache-mock</artifactId> <scope>test</scope> </dependency> @Test public void testPanacheMocking() { PanacheMock.mock(Person.class); Mockito.when(Person.count()).thenReturn(23l); Assertions.assertEquals(23, Person.count()); PanacheMock.verify(Person.class, Mockito.times(1)).coun t(); } DevServices When testing or running in dev mode Quarkus can even provide you with a zero con g database out of the box. Depending on your database type you may need docker installed in order to use this feature. The following open source databases: Postgresql (container) MySQL (container) MariaDB (container) H2 (in-process) Apache Derby (in-process) To use DevServices don’t con gure a database URL, username and password, Quarkus will provide the database and you can just start coding without worrying about con g. quarkus.datasource.db-kind=mariadb %prod.quarkus.datasource.jdbc.url=jdbc:mariadb://db:3306/my db %prod.quarkus.datasource.username=developer %prod.quarkus.datasource.password=developer Possible con guration values pre xed with quarkus.datasource: devservices If devservices is enabled or not. (default: true) devservices.image-name The container image name to use instead of the default one.
  • 15. devservices.properties Generic properties that are added to the database connection URL. DAO pattern Also supports DAO pattern with PanacheRepository<TYPE>. @ApplicationScoped public class DeveloperRepository implements PanacheRepository<Person> { public Person findByName(String name){ return find("name", name).firstResult(); } } EntityManager You can inject EntityManager in your classes: @Inject EntityManager em; @Inject org.hibernate.Session session; @Inject org.hibernate.SessionFactory sessionFactory; em.persist(car); Multiple datasources You can register more than one datasource. # default quarkus.datasource.db-kind=h2 quarkus.datasource.jdbc.url=jdbc:h2:tcp://localhost/mem:def ault .... # users datasource quarkus.datasource.users.devservices=false quarkus.datasource.users.db-kind=h2 quarkus.datasource.users.jdbc.url=jdbc:h2:tcp://localhost/m em:users Notice that after datasource you set the datasource name, in previous case users. You can inject then AgroalDataSource with io.quarkus.agroal.DataSource. @DataSource("users") AgroalDataSource dataSource1; Flushing You can force ush operation by calling .flush() or persistAndFlush() to make it in a single call This ush is less e cient and you still need to commit transaction. Testing There is a Quarkus Test Resource that starts and stops H2 server before and after test suite. Register dependency io.quarkus:quarkus-test-h2:test. And annotate the test: @QuarkusTestResource(H2DatabaseTestResource.class) public class FlywayTestResources { } Transactions The easiest way to de ne your transaction boundaries is to use the @Transactional annotation. Transactions are mandatory in case of none idempotent operations. @Transactional public void createDeveloper() {} You can control the transaction scope: @Transactional(REQUIRED) (default): starts a transaction if none was started, stays with the existing one otherwise. @Transactional(REQUIRES_NEW): starts a transaction if none was started; if an existing one was started, suspends it and starts a new one for the boundary of that method. @Transactional(MANDATORY): fails if no transaction was started ; works within the existing transaction otherwise. @Transactional(SUPPORTS): if a transaction was started, joins it ; otherwise works with no transaction. @Transactional(NOT_SUPPORTED): if a transaction was started, suspends it and works with no transaction for the boundary of the method; otherwise works with no transaction. @Transactional(NEVER): if a transaction was started, raises an exception; otherwise works with no transaction. You can con gure the default transaction timeout using quarkus.transaction-manager.default-transaction-timeout con guration property. By default it is set to 60 seconds. You can set a timeout property, in seconds, that applies to transactions created within the annotated method by using @TransactionConfiguration annotation. @Transactional @TransactionConfiguration(timeout=40) public void createDeveloper() {} If you want more control over transactions you can inject UserTransaction and use a programmatic way. @Inject UserTransaction transaction transaction.begin(); transaction.commit(); transaction.rollback(); You can implement your custom credentials provider (ie Azure KeyVault) to provide a username/password for the database connection. Name information is not necessary if there is only one custom credential provider. @ApplicationScoped @Unremovable @Named("my-credentials-provider") public class CustomCredentialsProvider implements Credentia lsProvider { @Inject Config config; @Override public Properties getCredentials(String credentials ProviderName) { properties.put(CredentialsProvider.USER_PROPERTY_NA ME, "hibernate_orm_test"); properties.put(CredentialsProvider.PASSWORD _PROPERTY_NAME, "hibernate_orm_test"); } } quarkus.datasource.credentials-provider= custom quarkus.datasource.credentials-provider-name= my-credentials-provider Hibernate Multitenancy Multitenancy is supported using Schema or Database approach. First you need to de ne how tenant is identi ed:
  • 16. @RequestScoped @Unremovable public class CustomTenantResolver implements TenantResolver { @Inject RoutingContext context; @Override public String getDefaultTenantId() { return "base"; } @Override public String resolveTenantId() { } } Schema approach quarkus.hibernate-orm.database.generation=none quarkus.hibernate-orm.multitenant=SCHEMA Database approach quarkus.hibernate-orm.database.generation=none quarkus.hibernate-orm.multitenant=DATABASE # default tenant quarkus.datasource.base.db-kind=postgresql quarkus.datasource.base.username=quarkus_test ... # Tenant 'mycompany' quarkus.datasource.mycompany.db-kind=postgresql quarkus.datasource.mycompany.username=mycompany quarkus.flyway.mycompany.locations=classpath:database/mycom pany ... If you need more dynamic approach implement: @ApplicationScoped io.quarkus.hibernate.orm.runtime.tenant.TenantConnectionResolver Hibernate Envers Quarkus supports Hibernate Envers. ./mvnw quarkus:add-extension -Dextensions="hibernate-envers" Con guration properties pre xed with quarkus.hibernate-envers: store-data-at-delete Enable store_data_at_delete feature. (default: false) audit-table-suffix De nes a su x for historical data table. (default: _AUD) audit-table-prefix De nes a pre x for historical data table. (default: ``) revision-field-name Revision eld name. (default: REV) revision-type-field-name Revision type eld name. (default: REVTYPE) REST Data Panache REST Data with Panache extension can generate the basic CRUD endpoints for your entities and repositories. ./mvnw quarkus:add-extension -Dextensions="hibernate-orm-rest-data-panache" You also need to add the JDBC driver extension and a JSON Marshaller (ie resteasy-jackson). Then you can de ne interfaces for de ning endpoints: In case of Active Record pattern: public interface DeveloperResource extends PanacheEntityRes ource<Developer, Long> { } In case of Repository: public interface DeveloperResource extends PanacheRepositor yResource<DeveloperRepository, Developer, Long> { } Quarkus will generate automatically the implementation for you following the next rules: Default path is a hyphenated lowercase resource name without a su x of resource or controller. get(@PathParam("id")), list, add(Developer), update(@PathParam("id"), Developer), delete(@PathParam("id")) You can customize these defaults by using @ResourceProperties and @MethodProperties annotations. @ResourceProperties(hal = true, path = "my-developer", halC ollectionName = "dev-collections") public interface DeveloperResource extends PanacheEntityRes ource<Developer, Long> { @MethodProperties(path = "all") List<Developer> list(); @MethodProperties(exposed = false) void delete(Long id); } If hal is true, you need to send the Accept: application/hal+json HTTP header to get the response. Hibernate Reactive ./mvnw quarkus:add-extension -Dextensions="quarkus-hibernate-reactive, quarkus-resteas y-mutiny, " Also you need to add the reactive driver (ie quarkus-reactive-pg- client). You can use: org.hibernate.reactive.mutiny.Mutiny or org.hibernate.reactive.stage.Stage. @Entity @Table(name = "dev") public class Developer { } @Inject CompletionStage<Stage.Session> stageSession; @Inject Uni<Mutiny.Session> mutinySession; public Uni<Long> reactivePersist() { return mutinySession .flatMap(s -> s.persist(new Developer(1, "Alex")) .flatMap(v -> session.flush()) .... } public CompletionStage<Developer> reactiveFind() { return stageSession .thenCompose(session -> { session.find(Developer.class, 1); }); } In nispan Quarkus integrates with In nispan: ./mvnw quarkus:add-extension -Dextensions="infinispan-client"
  • 17. Serialization uses a library called Protostream. Annotation based @ProtoFactory public Author(String name, String surname) { this.name = name; this.surname = surname; } @ProtoField(number = 1) public String getName() { return name; } @ProtoField(number = 2) public String getSurname() { return surname; } Initializer to set con guration settings. @AutoProtoSchemaBuilder(includeClasses = { Book.class, Author.class }, schemaPackageName = "book_sample") interface BookContextInitializer extends SerializationContextInitializer { } User written based There are three ways to create your schema: Proto le Creates a .proto le in the META-INF directory. package book_sample; message Author { required string name = 1; required string surname = 2; } In case of having a Collection eld you need to use the repeated key (ie repeated Author authors = 4). In code Setting proto schema directly in a produced bean. @Produces FileDescriptorSource bookProtoDefinition() { return FileDescriptorSource .fromString("library.proto", "package book_sample;n" + "message Author {n" + " required string name = 1;n" + " required string surname = 2;n" + "}"); } Marshaller Using org.infinispan.protostream.MessageMarshaller interface. public class AuthorMarshaller implements MessageMarshaller<Author> { @Override public String getTypeName() { return "book_sample.Author"; } @Override public Class<? extends Author> getJavaClass() { return Author.class; } @Override public void writeTo(ProtoStreamWriter writer, Author author) throws IOException { writer.writeString("name", author.getName()); writer.writeString("surname", author.getSurname()); } @Override public Author readFrom(ProtoStreamReader reader) throws IOException { String name = reader.readString("name"); String surname = reader.readString("surname"); return new Author(name, surname); } } And producing the marshaller: @Produces MessageMarshaller authorMarshaller() { return new AuthorMarshaller(); } In nispan Embedded ./mvnw quarkus:add-extension -Dextensions="infinispan-embeddedy" Con guration in infinispan.xml: <local-cache name="quarkus-transaction"> <transaction transaction-manager-lookup= "org.infinispan.transaction.lookup.JBossStandaloneJ TAManagerLookup"/> </local-cache> Set con guration le location in application.properties: quarkus.infinispan-embedded.xml-config=infinispan.xml And you can inject the main entry point for the cache: @Inject org.infinispan.manager.EmbeddedCacheManager cacheManager; DevServices When testing or running in dev mode Quarkus can even provide you with a zero con g In nispan out of the box. Possible con guration values pre xed with quarkus.infinispan- client: devservices.enabled If devservices is enabled or not. (default: true) devservices.port Optional xed port the dev service will listen to. If not de ned, the port will be chosen randomly. devservices.shared Indicates if the In nispan managed by Quarkus Dev Services is shared. When shared, Quarkus looks for running containers using label-based service discovery. (default: true) devservices.service-name The value of the quarkus-dev-service-infinispan label attached to the started container. (default: infinispan) devservices.artifacts List of the artifacts to automatically download and add to the In nispan server libraries. Redis Quarkus integrates with Redis. ./mvnw quarkus:add-extension -Dextensions="redis-client" Con gure Redis location:
  • 18. quarkus.redis.hosts=localhost:6379 You can use synchronous or reactive clients: @Inject RedisClient redisClient; @Inject ReactiveRedisClient reactiveRedisClient; void increment(String key, Integer incrementBy) { redisClient.incrby(key, incrementBy.toString()); } Uni<List<String>> keys() { return reactiveRedisClient .keys("*") .map(response -> { List<String> result = new ArrayList<>(); for (Response r : response) { result.add(r.toString()); } return result; }); } DevServices When testing or running in dev mode Quarkus can even provide you with a zero con g Redis out of the box. Possible con guration values pre xed with quarkus.redis: devservices.enabled If devservices is enabled or not. (default: true) devservices.image-name The container image name to use instead of the default one. devservices.port Optional xed port the dev service will listen to. If not de ned, the port will be chosen randomly. devservices.shared Indicates if the Redis broker managed by Quarkus Dev Services is shared. When shared, Quarkus looks for running containers using label-based service discovery. (default: true) devservices.service-name The value of the quarkus-dev-service-redis label attached to the started container. (default: redis) Multiple Redis Clients quarkus.redis.hosts = localhost:6379 quarkus.redis.second.hosts = localhost:6379 @Inject RedisClient defaultRedisClient; @Inject @RedisClientName("second") RedisClient redisClient2; List of Redis parameters. quarkus.redis as pre x is skipped in the next table. health.enabled Health check is published in case the smallrye-health extension is present. (default: true) password The Redis password. hosts The Redis hosts. (default: localhost:6379) database The Redis database. timeout The maximum delay to wait before a blocking command to redis server times out. (default: 10s) ssl Enables or disables the SSL on connect. clinet-type The Redis client type. Possible values: standalone, cluster, sentinel (default: standalone) Flyway Quarkus integrates with Flyway to help you on database schema migrations. ./mvnw quarkus:add-extension -Dextensions="quarkus-flyway" Then place migration les to the migrations folder (classpath:db/migration). You can inject org.flywaydb.core.Flyway to programmatically execute the migration. @Inject Flyway flyway; flyway.migrate(); Or can be automatically executed by setting migrate-at-start property to true quarkus.flyway.migrate-at-start=true List of Flyway parameters. quarkus.flyway as pre x is skipped in the next table. clean-at-start Execute Flyway clean command (default: false) migrate-at-start Flyway migration automatically (default: false) locations CSV locations to scan recursively for migrations. Supported pre xes classpath and filesystem (default: classpath:db/migration). connect-retries The maximum number of retries when attempting to connect (default: 0) schemas CSV case-sensitive list of schemas managed (default: none) table The name of Flyway’s schema history table (default: flyway_schema_history) out-of-order Allows migrations to be run "out of order". ignore-missing-migrations Ignore missing migrations when reading the history table. sql-migration-prefix Pre x for versioned SQL migrations (default: V) repeatable-sql-migration-prefix:: Pre x for repeatable SQL migrations (default: R) baseline-on-migrate Only migrations above baseline-version will then be applied baseline-version Version to tag an existing schema with when executing baseline (default: 1) baseline-description Description to tag an existing schema with when executing baseline (default: Flyway Baseline) validate-on-migrate Validate the applied migrations against the available ones (default: true) placeholder-prefix Pre x of every placeholder (default: ${)
  • 19. placeholder-suffix Su x of every placeholder (default: }) callbacks Comma-separated list of fully quali ed class names of Callback implementations. ignore-future-migrations Ignore future migrations when reading the history table. Multiple Datasources To use multiple datasource in Flyway you just need to add the datasource name just after the flyway property: quarkus.datasource.users.jdbc.url=jdbc:h2:tcp://localhost/m em:users quarkus.datasource.inventory.jdbc.url=jdbc:h2:tcp://localho st/mem:inventory # ... quarkus.flyway.users.schemas=USERS_TEST_SCHEMA quarkus.flyway.inventory.schemas=INVENTORY_TEST_SCHEMA # ... Liquibase Quarkus integrates with Liquibase to help you on database schema migrations. ./mvnw quarkus:add-extension -Dextensions="quarkus-liquibase" Then place changelog les to the (src/main/resources/db) folder. You can inject org.quarkus.liquibase.LiquibaseFactory to programmatically execute the migration. @Inject LiquibaseFactory liquibaseFactory; try (Liquibase liquibase = liquibaseFactory.createLiquibase ()) { ... } Or can be automatically executed by setting migrate-at-start property to true. quarkus.liquibase.migrate-at-start=true List of Liquibase parameters. quarkus.liquibase as pre x is skipped in the next table. change-log The change log le. XML, YAML , JSON, SQL formats supported. (default: db/changeLog.xml) change-log-parameters."<parameter-name>" Liquibase changelog parameters. migrate-at-start The migrate at start ag. (default: false) validate-on-migrate The validate on update ag. (default: false) clean-at-start The clean at start ag. (default: false) contexts The list of contexts. labels The list of labels. database-change-log-table-name The database change log lock table name. (default: DATABASECHANGELOG) database-change-log-lock-table-name The database change log lock table name. (default: DATABASECHANGELOGLOCK) default-catalog-name The default catalog name. default-schema-name The default schema name. liquibase-catalog-name The liquibase tables catalog name. liquibase-schema-name The liquibase tables schema name. liquibase-tablespace-name The liquibase tables tablespace name. Multiple Datasources To use multiple datasource in Liquibase you just need to add the datasource name just after the liquibase property: quarkus.datasource.users.jdbc.url=jdbc:h2:tcp://localhost/m em:users quarkus.datasource.inventory.jdbc.url=jdbc:h2:tcp://localho st/mem:inventory # ... quarkus.liquibase.users.schemas=USERS_TEST_SCHEMA quarkus.liquibase.inventory.schemas=INVENTORY_TEST_SCHEMA # ... Liquibase MongoDB ./mvnw quarkus:add-extension -Dextensions="liquibase-mongodb" Most of the con guration properties are valid but changing pre x to: quarkus.liquibase-mongodb Hibernate Search Quarkus integrates with Elasticsearch to provide a full-featured full- text search using Hibernate Search API. ./mvnw quarkus:add-extension -Dextensions="quarkus-hibernate-search-elasticsearch" You need to annotate your model with Hibernate Search API to index it: @Entity @Indexed public class Author extends PanacheEntity { @FullTextField(analyzer = "english") public String bio; @FullTextField(analyzer = "name") @KeywordField(name = "firstName_sort", sortable = Sortable.YES, normalizer = "sort") public String firstName; @OneToMany @IndexedEmbedded public List<Book> books; } It is not mandatory to use Panache. You need to de ne the analyzers and normalizers de ned in annotations. You only need to implement ElasticsearchAnalysisConfigurer interface and con gure it.
  • 20. public class MyQuarkusAnalysisConfigurer implements ElasticsearchAnalysisConfigurer { @Override public void configure( ElasticsearchAnalysisDefinitionContainerContext ct x) { ctx.analyzer("english").custom() .withTokenizer("standard") .withTokenFilters("asciifolding", "lowercase", "porter_stem"); ctx.normalizer("sort").custom() .withTokenFilters("asciifolding", "lowercase"); } } Use Hibernate Search in REST service: public class LibraryResource { @Inject EntityManager em; @Transactional public List<Author> searchAuthors( @QueryParam("pattern") String pattern) { return Search.getSearchSession(em) .search(Author.class) .predicate(f -> pattern == null || pattern.isEmpty() ? f.matchAll() : f.simpleQueryString() .onFields("firstName", "lastName", "books.title") .matching(pattern) ) .sort(f -> f.byField("lastName_sort") .then().byField("firstName_sort")) .fetchHits(); } When not using Hibernate ORM, index data using Search.getSearchSession(em).createIndexer() .startAndWait() at startup time. Con gure the extension in application.properties: quarkus.hibernate-search.elasticsearch.version=7 quarkus.hibernate-search.elasticsearch. analysis-configurer=MyQuarkusAnalysisConfigurer quarkus.hibernate-search.elasticsearch. automatic-indexing.synchronization-strategy=searchable quarkus.hibernate-search.elasticsearch. index-defaults.lifecycle.strategy=drop-and-create quarkus.hibernate-search.elasticsearch. index-defaults.lifecycle.required-status=yellow List of Hibernate-Elasticsearch properties pre xed with quarkus.hibernate-search.elasticsearch: backends Map of con guration of additional backends. version Version of Elasticsearch analysis-configurer Class or name of the neab used to con gure. hosts List of Elasticsearch servers hosts. enabled Whether Hibernate Search is enabled. (default: true) username Username for auth. password Password for auth. connection-timeout Duration of connection timeout. max-connections Max number of connections to servers. max-connections-per-route Max number of connections to server. indexes Per-index speci c con guration. discovery.enabled Enables automatic discovery. discovery.refresh-interval Refresh interval of node list. discovery.default-scheme Scheme to be used for the new nodes. automatic-indexing.synchronization-strategy Status for which you wait before considering the operation completed (queued,committed or searchable). automatic-indexing.enable-dirty-check When enabled, re-indexing of is skipped if the changes are on properties that are not used when indexing. index-defaults.lifecycle.strategy Index lifecycle (none, validate, update, create, drop-and-create, drop-abd-create-drop) index-defaults lifecycle required-status Minimal cluster status (green, yellow, red) index-defaults.lifecycle.required-status-wait-timeout Waiting time before failing the bootstrap. index-defaults.refresh-after-write Set if index should be refreshed after writes. Possible annotations: @Indexed Register entity as full text index @FullTextField Full text search. Need to set an analyzer to split tokens. @KeywordField The string is kept as one single token but can be normalized. IndexedEmbedded Include the Book elds into the Author index. @ContainerExtraction Sets how to extract a value from container, e.g from a Map. @DocumentId Map an unusual entity identi er to a document identi er. @GenericField Full text index for any supported type. @IdentifierBridgeRef Reference to the identi er bridge to use for a @DocumentId. @IndexingDependency How a dependency of the indexing process to a property should affect automatic reindexing. @ObjectPath @ScaledNumberField For java.math.BigDecimal or java.math.BigInteger that you need higher precision. If you are using ElasticSearch in AWS you might need some extra con g provided by an special extension https://quarkiverse.github.io/quarkiverse-docs/quarkus-hibernate- search-extras/dev/index.html Amazon DynamoDB Quarkus integrates with https://aws.amazon.com/dynamodb/: ./mvnw quarkus:add-extension -Dextensions="quarkus-amazon-dynamodb"
  • 21. @Inject DynamoDbClient dynamoDB; To use asycnhronous client with Mutiny: ./mvnw quarkus:add-extension -Dextensions="quarkus-amazon-dynamodb, resteasy-mutiny" @Inject DynamoDbAsyncClient dynamoDB; Uni.createFrom().completionStage(() -> dynamoDB.scan(scanRe quest())).... To use it as a local DynamoDB instance: quarkus.dynamodb.region= eu-central-1 quarkus.dynamodb.endpoint-override= http://localhost:8000 quarkus.dynamodb.credentials.type=STATIC quarkus.dynamodb.credentials.static-provider .access-key-id=test-key quarkus.dynamodb.credentials.static-provider .secret-access-key=test-secret If you want to work with an AWS account, you’d need to set it with: quarkus.dynamodb.region=<YOUR_REGION> quarkus.dynamodb.credentials.type=DEFAULT DEFAULT credentials provider chain: System properties aws.accessKeyId, aws.secretKey Env. Varables AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY Credentials pro le ~/.aws/credentials Credentials through the Amazon EC2 container service if the AWS_CONTAINER_CREDENTIALS_RELATIVE_URI set Credentials through Amazon EC2 metadata service. Con guration parameters pre xed with quarkus.dynamodb: Parameter Default Description enable-endpoint- discovery false Endpoint discovery for a service API that supports endpoint discovery. endpoint-override Con gure the endpoint with which the SDK should communicate. api-call-timeout Time to complete an execution. interceptors List of class interceptors. Con guration parameters pre xed with quarkus.dynamodb.aws: Parameter Default Description region Region that hosts DynamoDB. credentials.type DEFAULT Credentials that should be used DEFAULT, STATIC, SYSTEM_PROPERTY, ENV_VARIABLE, PROFILE, CONTAINER, INSTANCE_PROFILE, PROCESS, ANONYMOUS Credentials speci c parameters pre xed with quarkus.dynamodb.aws.credentials: Parameter Default Description DEFAULT default- provider.async- credential-update- enabled false Should fetch credentials async. default- provider.reuse-last- provider-enabled true Should reuse the last successful credentials. STATIC static- provider.access-key- id AWS access key id. static- provider.secret- access-key AWS secret access key. Parameter Default Description PROFILE profile- provider.profile-name default The name of the pro le to use. PROCESS process- provider.command Command to execute to retrieve credentials. process- provider.process- output-limit 1024 Max bytes to retrieve from process. process- provider.credential- refresh-threshold PT15S The amount of time between credentials expire and credentials refreshed. process- provider.async- credential-update- enabled false Should fetch credentials async. In case of synchronous client, the next parameters can be con gured pre xed by quarkus.dynamodb.sync-client: Parameter Default Description connection- acquisition-timeout 10S Connection acquisation timeout. connection-max-idle- time 60S Max time to connection to be opened. connection-timeout Connection timeout. connection-time-to- live 0 Max time connection to be open. socket-timeout 30S Time to wait for data. max-connections 50 Max connections. expect-continue- enabled true Client send an HTTP expect-continue handsake.
  • 22. Parameter Default Description use-idle-connection- reaper true Connections in pool should be closed asynchronously. proxy.endpoint Endpoint of the proxy server. proxy.enabled false Enables HTTP proxy. proxy.username Proxy username. proxy.password Proxy password. proxy.ntlm-domain For NTLM, domain name. proxy.ntlm- workstation For NTLM, workstation name. proxy.preemptive- basic-authentication- enabled Authenticate pre- emptively. proxy.non-proxy- hosts List of non proxy hosts. tls-managers- provider.type system-property TLS manager: none, system-property, file-store tls-managers- provider.file- store.path Path to key store. tls-managers- provider.file- store.type Key store type. tls-managers- provider.file- store.password Key store password. In case of asynchronous client, the next parameters can be con gured pre xed by quarkus.dynamodb.async-client: Parameter Default Description connection- acquisition-timeout 10S Connection acquisation timeout. Parameter Default Description connection-max-idle- time 60S Max time to connection to be opened. connection-timeout Connection timeout. connection-time-to- live 0 Max time connection to be open. max-concurrency 50 Max number of concurrent connections. use-idle-connection- reaper true Connections in pool should be closed asynchronously. read-timeout 30S Read timeout. write-timeout 30S Write timeout. proxy.endpoint Endpoint of the proxy server. proxy.enabled false Enables HTTP proxy. proxy.non-proxy- hosts List of non proxy hosts. tls-managers- provider.type system-property TLS manager: none, system-property, file-store tls-managers- provider.file- store.path Path to key store. tls-managers- provider.file- store.type Key store type. tls-managers- provider.file- store.password Key store password. ssl-provider SSL Provider (jdk, openssl, openssl- refcnt). Parameter Default Description protocol HTTP_1_1 Sets the HTTP protocol. max-http2-streams Max number of concurrent streams. event-loop.override false Enable custom event loop conf. event-loop.number-of- threads Number of threads to use in event loop. event-loop.thread- name-prefix aws-java-sdk- NettyEventLoop Pre x of thread names. Amazon S3 ./mvnw quarkus:add-extension -Dextensions="quarkus-amazon-s3" @Inject S3Client s3Client; You need to set a HTTP client either URL Connection: <dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>url-connection-client</artifactId> </dependency> or Apache HTTP: <dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>apache-client</artifactId> </dependency> quarkus.s3.sync-client.type=apache And con gure it:
  • 23. quarkus.s3.endpoint-override=http://localhost:8008 quarkus.s3.interceptors=io.quarkus.it.amazon.s3.S3ModifyRes ponse quarkus.s3.aws.region=us-east-1 quarkus.s3.aws.credentials.type=static quarkus.s3.aws.credentials.static-provider.access-key-id=te st-key quarkus.s3.aws.credentials.static-provider.secret-access-ke y=test-secret You can inject asynchronous client too: @Inject S3AsyncClient s3AsyncClient; And you need to add the asynchronous Netty client: <dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>netty-nio-client</artifactId> </dependency> Con guration properties are the same as Amazon DynamoDB but changing the pre x from dynamodb to s3. Neo4j Quarkus integrates with Neo4j: ./mvnw quarkus:add-extension -Dextensions="quarkus-neo4j" @Inject org.neo4j.driver.Driver driver; Con guration properties: quarkus.neo4j as pre x is skipped in the next table. Pre x is quarkus.neo4j. uri URI of Neo4j. (default: localhost:7687) authentication.username Username. (default: neo4j) authentication.password Password. (default: neo4j) authentication.disabled Disable authentication. (default: false) Enable metrics. (default: false) pool.log-leaked-sessions Enable leaked sessions logging. (default:`false`) pool.max-connection-pool-size Max amount of connections. (default: 100) pool.max-connection-lifetime Pooled connections older will be closed and removed from the pool. (default: 1H) pool.connection-acquisition-timeout Timout for connection adquisation. (default: 1M) pool.idle-time-before-connection-test Pooled connections idled in the pool for longer than this timeout will be tested before they are used. (default: -1) As Neo4j uses SSL communication by default, to create a native executable you need to compile with next options GraalVM options: -H:EnableURLProtocols=http,https --enable-all-security-services - H:+JNI And Quarkus Maven Plugin with next con guration: <artifactId>quarkus-maven-plugin</artifactId> <executions> <execution> <id>native-image</id> <goals> <goal>native-image</goal> </goals> <configuration> <enableHttpUrlHandler>true </enableHttpUrlHandler> <enableHttpsUrlHandler>true </enableHttpsUrlHandler> <enableAllSecurityServices>true </enableAllSecurityServices> <enableJni>true</enableJni> </configuration> </execution> </executions> Alternatively, and as a not recommended way in production, you can disable SSL and Quarkus will disable Bolt SSL as well. quarkus.ssl.native=false. If you are using Neo4j 4.0, you can use fully reactive. Add the next extension: quarkus-resteasy-mutiny. @GET public Publisher<String> get() { return Multi.createFrom().resource(driver::rxSession, session -> session.readTransaction(tx -> { RxResult result = tx.run("MATCH (f:Fruit) RETUR N f.name as name"); return Multi.createFrom().publisher(result.reco rds()) .map(record -> record.get("name").asStr ing()); }) ).withFinalizer(session -> { return Uni.createFrom().publisher(session.close()); }); } DevServices When testing or running in dev mode Quarkus can even provide you with a zero con g Neo4j out of the box. Possible con guration values are shown at Neo4J MongoDB Client Quarkus integrates with MongoDB: ./mvnw quarkus:add-extension -Dextensions="quarkus-mongodb-client" @Inject com.mongodb.client.MongoClient client; @Inject io.quarkus.mongodb.reactive.ReactiveMongoClient client; INFO: Reactive client uses exposes Mutiny API. quarkus.mongodb.connection-string=mongodb://localhost:27018 quarkus.mongodb.write-concern.journal=false Testing To start an embedded MongoDB database for your unit tests, Quarkus provides two QuarkusTestResourceLifecycleManager. Add io.quarkus:quarkus-test-mongodb dependency. // Single MongoDB instance @QuarkusTestResource(io.quarkus.test.mongodb.MongoTestResou rce.class) // ReplicaSet with two instances @QuarkusTestResource(io.quarkus.test.mongodb.MongoReplicaSe tTestResource.class)
  • 24. Multi MongoDB support You can con gure multiple MongoDB clients using same approach as with DataSource. The syntax is quarkus.mongodb.<optional name>. <property>: quarkus.mongodb.users.connection-string = mongodb://mongo2: 27017/userdb quarkus.mongodb.inventory.connection-string = mongodb://mon go3:27017/invdb Inject the instance using @io.quarkus.mongodb.runtime.MongoClientName annotation: @Inject @MongoClientName("users") MongoClient mongoClient1; DevServices When testing or running in dev mode Quarkus can even provide you with a zero con g MongoDB database out of the box. %prod.quarkus.mongodb.connection-string=mongodb://localhos t:27018 Possible con guration values pre xed with quarkus.datasource: devservices.enabled If devservices is enabled or not. (default: true) devservices.image-name The container image name to use instead of the default one. devservices.port Optional xed port the dev service will listen to. If not de ned, the port will be chosen randomly. devservices.properties Generic properties that are added to the database connection URL. quarkus.mongodb as pre x is skipped in the following table. Parameter Type Description connection-string String MongoDB connection URI. hosts List<String> Addresses passed as host:port. application-name String Application name. max-pool-size Int Maximum number of connections. min-pool-size Int Minimum number of connections. max-connection-idle- time Duration Idle time of a pooled connection. max-connection-life- time Duration Life time of pooled connection. wait-queue-timeout Duration Maximum wait time for new connection. maintenance- frequency Duration Time period between runs of maintenance job. maintenance-initial- delay Duration Time to wait before running the rst maintenance job. wait-queue-multiple Int Multiplied with max- pool-size gives max numer of threads waiting. connection-timeout Duration socket-timeout Duration tls-insecure boolean [false] Insecure TLS. tls boolean [false] Enable TLS Parameter Type Description replica-set-name String Implies hosts given are a seed list. server-selection- timeout Duration Time to wait for server selection. local-threshold Duration Minimum ping time to make a server eligible. heartbeat-frequency Duration Frequency to determine the state of servers. read-preference primary, primaryPreferred, secondary, secondaryPreferred, nearest Read preferences. max-wait-queue-size Int Max number of concurrent operations allowed to wait. write-concern.safe boolean [true] Ensures are writes are ack. write- concern.journal boolean [true] Journal writing aspect. write-concern.w String Value to all write commands. write-concern.retry- writes boolean [false] Retry writes if network fails. write-concern.w- timeout Duration Timeout to all write commands. credentials.username String Username. credentials.password String Password. credentials.auth- mechanism MONGO-CR, GSSAPI, PLAIN, MONGODB-X509
  • 25. Parameter Type Description credentials.auth- source String Source of the authentication credentials. credentials.auth- mechanism-properties Map<String, String> Authentication mechanism properties. read-concern String Con gures the read concern. Possible values: local, majority, linearizable, snapshot, available MongoDB Panache You can also use the Panache framework to write persistence part when using MongoDB. ./mvnw quarkus:add-extension -Dextensions="mongodb-panache" MongoDB con guration comes from MongoDB Client section. @MongoEntity(collection="ThePerson") public class Person extends PanacheMongoEntity { public String name; @BsonProperty("birth") public LocalDate birthDate; public Status status; } Possible annotations in elds: @BsonId (for custom ID), @BsonProperty and @BsonIgnore. @MongoEntity is optional. Multi-tenancy with MongoDB Panache @MongoEntity(collection = "TheBook", clientName = "client2" , database = "database2") Methods provided are similar of the ones shown in Persistence section. person.persist(); person.update(); person.delete(); List<Person> allPersons = Person.listAll(); person = Person.findById(personId); List<Person> livingPersons = Person.list("status", Status.A live); List<Person> persons = Person.list(Sort.by("name").and("bir th")); long updated = Person.update("name", "Mortal").where("statu s", Status.Alive); long countAll = Person.count(); Person.deleteById(id); Person.delete("status", Status.Alive); All list methods have equivalent stream versions. Pagination You can also use pagination: PanacheQuery<Person> livingPersons = Person.find("status", Status.Alive); livingPersons.page(Page.ofSize(25)); // get the first page List<Person> firstPage = livingPersons.list(); // get the second page List<Person> secondPage = livingPersons.nextPage().list(); Range PanacheQuery<Person> livingPersons = Person .find("status", Status.Alive); List<Person> secondRange = livingPersons.range(25, 49).list (); You cannot mix pagination and range. Queries Native MongoDB queries are supported (if they start with { or org.bson.Document instance) as well as Panache Queries. Panache Queries equivalence in MongoDB: firstname = ?1 and status = ?2 → {'firstname': ?1, 'status': ? 2} amount > ?1 and firstname != ?2 → {'amount': {'$gt': ?1}, 'firstname': {'$ne': ?2}} lastname like ?1 → {'lastname': {'$regex': ?1}} lastname is not null → {'lastname':{'$exists': true}} PanacheQL refers to the Object parameter name but native queries refer to MongoDB eld names. Projection Projection can be done for both PanacheQL and native queries. import io.quarkus.mongodb.panache.ProjectionFor; @ProjectionFor(Person.class) (1) public class PersonName { public String name; } PanacheQuery<PersonName> shortQuery = Person.find("status " , Status.Alive).project(PersonName.class); 1 Entity class. Transsactions To use them with MongoDB with Panache you need to annotate the method that starts the transaction with the @Transactional annotation. Testing To mock using active record pattern: <dependency> <groupId>io.quarkus</groupId> <artifactId>quarkus-panache-mock</artifactId> <scope>test</scope> </dependency> @Test public void testPanacheMocking() { PanacheMock.mock(Person.class); Mockito.when(Person.count()).thenReturn(23l); Assertions.assertEquals(23, Person.count()); PanacheMock.verify(Person.class, Mockito.times(1)).coun t(); } DAO pattern @ApplicationScoped public class PersonRepository implements PanacheMongoRepository<Person> { } Jandex If entities are de ned in external JAR, you need to enable in these projects the Jandex plugin in project.
  • 26. <plugin> <groupId>org.jboss.jandex</groupId> <artifactId>jandex-maven-plugin</artifactId> <version>1.0.3</version> <executions> <execution> <id>make-index</id> <goals> <goal>jandex</goal> </goals> </execution> </executions> <dependencies> <dependency> <groupId>org.jboss</groupId> <artifactId>jandex</artifactId> <version>2.1.1.Final</version> </dependency> </dependencies> </plugin> Panache includes an annotation processor that enhance your entities. If you disable annotation processors you might need to create a marker le on Panache archives at META-INF/panache- archive.marker manually. Reactive Panache MongoDB with Panache allows using reactive implementation too by using ReactivePanacheMongoEntity or ReactivePanacheMongoEntityBase or ReactivePanacheMongoRepository or ReactivePanacheMongoRepositoryBase depending on your style. public class ReactivePerson extends ReactivePanacheMongoEnt ity { public String name; } CompletionStage<Void> cs1 = person.persist(); CompletionStage<List<ReactivePerson>> allPersons = Reactive Person.listAll(); Publisher<ReactivePerson> allPersons = ReactivePerson.strea mAll(); Uni<List<PersonName>> persons = ReactivePersonEntity.find( "lastname", name).project(PersonName.class).list(); MongoDB REST Data Panache MongoDB REST Data with Panache extension can generate the basic CRUD endpoints for your entities and repositories. ./mvnw quarkus:add-extension -Dextensions="mongodb-rest-data-panache" You also need to add the JDBC driver extension and a JSON Marshaller (ie resteasy-jackson). Then you can de ne interfaces for de ning endpoints: In case of Active Record pattern: public interface DeveloperResource extends PanacheMongoEnti tyResource<Developer, Long> { } In case of Repository: public interface DeveloperResource extends PanacheMongoRepo sitoryResource<DeveloperRepository, Developer, Long> { } Cassandra Quarkus integrates with Cassandra and DataStax Object Mapper. <dependency> <groupId>com.datastax.oss.quarkus</groupId> <artifactId>cassandra-quarkus-client</artifactId> </dependency> Enities and DAOs are generated as you have been doing with DataStax Object Mapper. You need to create a DaoProducer: @Inject public FruitDaoProducer(QuarkusCqlSession session) { FruitMapper mapper = new FruitMapperBuilder(session).buil d(); fruitDao = mapper.fruitDao(); } @Produces @ApplicationScoped FruitDao produceFruitDao() { return fruitDao; } Cassandra con guration: quarkus.cassandra.contact-points=127.0.0.1:9042 quarkus.cassandra.local-datacenter=datacenter1 quarkus.cassandra.keyspace=k1 quarkus.cassandra.auth.username=john quarkus.cassandra.auth.password=s3cr3t You can con gure other Cassandra Java driver settings using application.conf or application.json les. They need to be located in the classpath of your application. Driver settings reference. If MicroPro le Metrics extension is registered, the Cassandra extension can provide (if enabled) metrics about the session: quarkus.cassandra.metrics.enabled=true quarkus.cassandra.metrics.session-enabled=connected-nodes,b ytes-sent quarkus.cassandra.metrics.node-enabled=pool.open-connection s Reactive You can also use Mutiny to de ne a reactive DAO: @Dao public interface FruitDaoReactive { @Update Uni<Void> update(Fruit fruit); @Select MutinyMappedReactiveResultSet<Fruit> findById(String stor eId); } @Mapper public interface FruitMapper { @DaoFactory FruitDaoReactive fruitDaoReactive(); }
  • 27. Reactive Programming Quarkus implements MicroPro le Reactive spec and uses RXJava2 to provide reactive programming model. ./mvnw quarkus:add-extension -Dextensions="quarkus-smallrye-reactive-streams-operator s" Asynchronous HTTP endpoint is implemented by returning Java CompletionStage. You can create this class either manually or using MicroPro le Reactive Streams spec: @GET @Path("/reactive") @Produces(MediaType.TEXT_PLAIN) public CompletionStage<String> getHello() { return ReactiveStreams.of("h", "e", "l", "l", "o") .map(String::toUpperCase) .toList() .run() .thenApply(list -> list.toString()); } Creating streams is also easy, you just need to return Publisher object. @GET @Path("/stream") @Produces(MediaType.SERVER_SENT_EVENTS) public Publisher<String> publishers() { return Flowable .interval(500, TimeUnit.MILLISECONDS) .map(s -> atomicInteger.getAndIncrement()) .map(i -> Integer.toString(i)); } Mutiny and JAX-RS Apart from the CompletionStage support, there is also support for Mutiny. ./mvnw quarkus:add-extension -Dextensions="quarkus-resteasy-mutiny" @GET @Produces(MediaType.TEXT_PLAIN) public Uni<String> hello() { return Uni.createFrom().item(() -> "hello"); } @GET @Produces(MediaType.TEXT_PLAIN) public Multi<String> multi() { return Multi.createFrom().items("hello", "world"); } Mutiny Quarkus integrates with Mutiny as reactive programming library: ./mvnw quarkus:add-extension -Dextensions="mutiny" @ApplicationScoped public static class ReactiveHello { public Uni<String> greeting() { return Uni.createFrom().item(() -> "hello") .emitOn(Infrastructure.getDefaultExecutor ()); } public Multi<String> stream() { return Multi.createFrom().items("hello", "world") .emitOn(Infrastructure.getDefaultExecutor ()); } } Converting from/to RxJava2 or Reactor APIs: RxJava 2 <dependency> <groupId>io.smallrye.reactive</groupId> <artifactId>mutiny-rxjava</artifactId> </dependency> From RxJava2: Uni<Void> uniFromCompletable = Uni.createFrom() .converter(UniRxConvert ers.fromCompletable(), completable); Uni<String> uniFromSingle = Uni.createFrom() .converter(UniRxConverters. fromSingle(), single); Uni<String> uniFromObservable = Uni.createFrom() .converter(UniRxConverters. fromObservable(), observable); Uni<String> uniFromFlowable = Uni.createFrom() .converter(UniRxConverters. fromFlowable(), flowable); ... Multi<Void> multiFromCompletable = Multi.createFrom() .converter(MultiRxC onverters.fromCompletable(), completable); Multi<String> multiFromObservable = Multi.createFrom() .converter(MultiRxC onverters.fromObservable(), observable); Multi<String> multiFromFlowable = Multi.createFrom() .converter(MultiRxC onverters.fromFlowable(), flowable); ... To RxJava2: Completable completable = uni.convert().with(UniRxConverter s.toCompletable()); Single<Optional<String>> single = uni.convert().with(UniRxC onverters.toSingle()); Observable<String> observable = uni.convert().with(UniRxCon verters.toObservable()); Flowable<String> flowable = uni.convert().with(UniRxConvert ers.toFlowable()); ... Completable completable = multi.convert().with(MultiRxConve rters.toCompletable()); Single<Optional<String>> single = multi.convert().with(Mult iRxConverters.toSingle()); Observable<String> observable = multi.convert().with(MultiR xConverters.toObservable()); Flowable<String> flowable = multi.convert().with(MultiRxCon verters.toFlowable()); ... Reactor API <dependency> <groupId>io.smallrye.reactive</groupId> <artifactId>mutiny-reactor</artifactId> </dependency> From Reactor:
  • 28. Uni<String> uniFromMono = Uni.createFrom().converter(UniRea ctorConverters.fromMono(), mono); Uni<String> uniFromFlux = Uni.createFrom().converter(UniRea ctorConverters.fromFlux(), flux); Multi<String> multiFromMono = Multi.createFrom().converter (MultiReactorConverters.fromMono(), mono); Multi<String> multiFromFlux = Multi.createFrom().converter (MultiReactorConverters.fromFlux(), flux); To Reactor: Mono<String> mono = uni.convert().with(UniReactorConverter s.toMono()); Flux<String> flux = uni.convert().with(UniReactorConverter s.toFlux()); Mono<String> mono2 = multi.convert().with(MultiReactorConve rters.toMono()); Flux<String> flux2 = multi.convert().with(MultiReactorConve rters.toFlux()); CompletionStages or Publisher CompletableFuture<String> future = Uni .createFrom().completionStage(CompletableFuture.sup plyAsync(() -> "hello")); CompletationStage<String> cs = Uni .createFrom().subscribeAsCompletionStage(); Multi implements Publisher. RESTEasy Reactive RESTEasy Reactive is a new implementation of JAX-RS but fully reactive. mvn quarkus:add-extension -Dextensions="quarkus-resteasy-reactive" package org.acme.rest; import javax.ws.rs.GET; import javax.ws.rs.Path; @Path("rest") public class Endpoint { @Path("hello") @GET public String hello(){ // executed in event-loop return "Hello, World!"; } @GET public Uni<Book> culinaryGuide(){ // executed in event-loop but not blocking return Book.findByIsbn("978-2081229297"); } @io.smallrye.common.annotation.Blocking @GET public String blockingHello() throws InterruptedExcepti on { // executed in worker-thread return "Yaaaawwwwnnnnnn…"; } } Reactive Messaging Quarkus relies on MicroPro le Reactive Messaging spec to implement reactive messaging streams. mvn quarkus:add-extension -Dextensions=" io.quarkus:quarkus-smallrye-reactive-messaging" You can just start using in-memory streams by using @Incoming to produce data and @Outgoing to consume data. Produce every 5 seconds one piece of data. @ApplicationScoped public class ProducerData { @Outgoing("my-in-memory") public Flowable<Integer> generate() { return Flowable.interval(5, TimeUnit.SECONDS) .map(tick -> random.nextInt(100)); } } or in Mutiny: @ApplicationScoped public class ProducerData { @Outgoing("my-in-memory") public Multi<Integer> generate() { return Multi.createFrom().ticks().every(Duration.of Seconds(5)) .onItem().apply(n -> random.nextInt(100)); } } If you want to dispatch to all subscribers you can annotate the method with @Broadcast. Consumes generated data from my-in-memory stream. @ApplicationScoped public class ConsumerData { @Incoming("my-in-memory") public void randomNumber(int randomNumber) { System.out.println("Received " + randomNumber); } } You can also inject an stream as a eld: @Inject @Stream("my-in-memory") Publisher<Integer> randomRumbers; @Inject @Stream("generated-price") Emitter<String> emitter; Patterns REST API → Message @Inject @Stream(“in”) Emitter<String> emitter; emitter.send(message); Message → Message @Incoming(“in”) @Outgoing(“out”) public String process(String in) { } Message → SSE
  • 29. @Inject @Stream(“out”) Publisher<String> result; @GET @Produces(SERVER_SENT_EVENTS) public Publisher<String> stream() { return result; } Message → Business Logic @ApplicationScoped public class ReceiverMessages { @Incoming("prices") public void print(String price) { } } To indicate that the method should be executed on a worker pool you can use @Blocking: @Outgoing("Y") @Incoming("X") @Blocking To customize: @Blocking(value="my-custom-pool", ordered = false) smallrye.messaging.worker.my-custom-pool.max-concurrency=3 Possible implementations are: In-Memory If the stream is not con gured then it is assumed to be an in- memory stream, if not then stream type is de ned by connector eld. Kafka To integrate with Kafka you need to add next extensions: mvn quarkus:add-extension -Dextensions=" io.quarkus:quarkus-smallrye-reactive-messaging-kafka" Then @Outgoing, @Incoming or @Stream can be used. Kafka con guration schema: mp.messaging.[outgoing|incoming]. {stream-name}.<property>=<value>. The connector type is smallrye-kafka. mp.messaging.outgoing.generated-price.connector= smallrye-kafka mp.messaging.outgoing.generated-price.topic= prices mp.messaging.outgoing.generated-price.bootstrap.servers= localhost:9092 mp.messaging.outgoing.generated-price.value.serializer= org.apache.kafka.common.serialization.IntegerSerializer mp.messaging.incoming.prices.connector= smallrye-kafka mp.messaging.incoming.prices.value.deserializer= org.apache.kafka.common.serialization.IntegerDeserializ er A complete list of supported properties are in Kafka site. For the producer and for consumer JSON-B Serializer/Deserializer You can use JSON-B to serialize/deserialize objects. ./mvnw quarkus:add-extension -Dextensions="quarkus-kafka-client" To serialize you can use io.quarkus.kafka.client.serialization.JsonbSerializer. To deserialize you need to extend io.quarkus.kafka.client.serialization.JsonbDeserializer and provide a type. public class BeerDeserializer extends JsonbDeserializer<Beer> { public BeerDeserializer() { super(Beer.class); } } DevServices When testing or running in dev mode Quarkus can even provide you with a zero con g Kafka out of the box. Possible con guration values pre xed with quarkus.kafka: devservices.enabled If devservices is enabled or not. (default: true) devservices.image-name The container image name to use instead of the default one. (default: docker.io/vectorized/redpanda:v21.5.5) devservices.port Optional xed port the dev service will listen to. If not de ned, the port will be chosen randomly. devservices.shared Indicates if the Kafka broker managed by Quarkus Dev Services is shared. When shared, Quarkus looks for running containers using label-based service discovery. (default: true) devservices.service-name The value of the quarkus-dev-service-kafka label attached to the started container. (default: kafka) devservices.topic-partitions-timeout Timeout for admin client calls used in topic creation. (default: 2S) devservices.topic-partitions The topic-partition pairs to create in the Dev Services Kafka broker. Example: quarkus.kafka.devservices.topic- partitions.test=2 will create a topic named test with 2 partitions Apicurio Registry Avro You can use Apicurio Registry Avro. ./mvnw quarkus:add-extension -Dextensions="apicurio-registry-avro" Place schemas at src/main/avro/ directory. application.properties mp.messaging.outgoing.movies.connector=smallrye-kafka mp.messaging.outgoing.movies.topic=movies # automatically register the schema with the registry, if n ot present mp.messaging.outgoing.movies.apicurio.registry.auto-registe r=true # URL of registry mp.messaging.connector.smallrye-kafka.schema.registry.url=h ttp://localhost:8081 DevServices When testing or running in dev mode Quarkus can even provide you with a zero con g Apicurio Registry out of the box. Possible con guration values pre xed with quarkus.apicurio- registry: devservices.enabled If devservices is enabled or not. (default: true) devservices.image-name The container image name to use instead of the default one. (default: docker.io/apicurio/apicurio-registry-mem:2.1.3.Final) devservices.port Optional xed port the dev service will listen to. If not de ned, the port will be chosen randomly.
  • 30. devservices.shared Indicates if the Apicurio managed by Quarkus Dev Services is shared. When shared, Quarkus looks for running containers using label-based service discovery. (default: true) devservices.service-name The value of the quarkus-dev-service-apicurio-registry label attached to the started container. (default: apicurio-registry) AMQP To integrate with AMQP you need to add next extensions: ./mvnw quarkus:add-extension -Dextensions="reactive-messaging-amqp" Then @Outgoing, @Incoming or @Stream can be used. AMQP con guration schema: mp.messaging.[outgoing|incoming]. {stream-name}.<property>=<value>. Special properties amqp-username and amqp-password are used to con gure AMQP broker credentials. The connector type is smallrye-amqp. amqp-username=quarkus amqp-password=quarkus # write mp.messaging.outgoing.generated-price.connector= smallrye-amqp mp.messaging.outgoing.generated-price.address= prices mp.messaging.outgoing.generated-price.durable= true # read mp.messaging.incoming.prices.connector= smallrye-amqp mp.messaging.incoming.prices.durable= true A complete list of supported properties for AMQP. DevServices When testing or running in dev mode Quarkus can even provide you with a zero con g AMQP out of the box. Possible con guration values pre xed with quarkus.amqp: devservices.enabled If devservices is enabled or not. (default: true) devservices.image-name The container image name to use instead of the default one. (default: quay.io/artemiscloud/activemq-artemis-broker:0.1.2) devservices.port Optional xed port the dev service will listen to. If not de ned, the port will be chosen randomly. The value of the AMQ_EXTRA_ARGS environment variable to pass to the container. (default: --no-autotune --mapped --no-fsync) devservices.shared Indicates if the AMQP broker managed by Quarkus Dev Services is shared. When shared, Quarkus looks for running containers using label-based service discovery. (default: true) devservices.service-name The value of the quarkus-dev-service-aqmp label attached to the started container. (default: amqp) RabbitMQ To integrate with RabbitMQ you need to add next extensions: ./mvnw quarkus:add-extension -Dextensions="smallrye-reactive-messaging-rabbitmq" Then @Outgoing, @Incoming or @Stream can be used. The connector type is smallrye-rabbitmq. RabbitMQ con guration schema: mp.messaging.[outgoing|incoming]. {stream-name}.<property>=<value>. mp.messaging.incoming.requests.connector=smallrye-rabbitmq mp.messaging.incoming.requests.queue.name=quote-requests mp.messaging.incoming.requests.exchange.name=quote-requests mp.messaging.outgoing.quotes.connector=smallrye-rabbitmq mp.messaging.outgoing.quotes.exchange.name=quotes A complete list of supported properties for RabbitMQ. DevServices When testing or running in dev mode Quarkus can even provide you with a zero con g RabbitMQ out of the box. Possible con guration values pre xed with quarkus.rabbitmq: devservices.enabled If devservices is enabled or not. (default: true) devservices.image-name The container image name to use instead of the default one. (default: quay.io/kiegroup/kogito-data-index-ephemeral) devservices.port Optional xed port the dev service will listen to. If not de ned, the port will be chosen randomly. devservices.shared Indicates if the RabbitMQ managed by Quarkus Dev Services is shared. When shared, Quarkus looks for running containers using label-based service discovery. (default: true) devservices.service-name The value of the quarkus-dev-service-rabbitmq label attached to the started container. (default: rabbitmq) devservices.exchanges.<exchanges>.type Type of exchange: direct, topic, headers, fanout, etc. (default: direct) devservices.exchanges.<exchanges>.auto-delete Should the exchange be deleted when all queues are nished using it? (default: false) devservices.exchanges.<exchanges>.durable Should the exchange remain after restarts? devservices.exchanges.<exchanges>.arguments Extra arguments for the exchange de nition. devservices.queues.<queues>.auto-delete Should the queue be deleted when all consumers are nished using it? (default: false) devservices.queues.<queues>.durable Should the queue remain after restarts? (default: false) devservices.queues.<queues>.arguments Extra arguments for the queue de nition devservices.bindings.<bindings>.source Source exchange to bind to. Defaults to name of binding instance devservices.bindings.<bindings>.routing-key Routing key speci cation for the source exchange (default: #) devservices.bindings.<bindings>.destination Destination exchange or queue to bind to. Defaults to name of binding instance devservices.bindings.<bindings>.destination-type Destination type for binding: queue, exchange, etc. (default: queue) devservices.bindings.<bindings>.arguments Extra arguments for the binding de nition MQTT To integrate with MQTT you need to add next extensions: ./mvnw quarkus:add-extension -Dextensions="vertx, smallrye-reactive-streams-operator s smallrye-reactive-messaging" And add io.smallrye.reactive:smallrye-reactive-messaging-mqtt- 1.0:0.0.10 dependency in your build tool. Then @Outgoing, @Incoming or @Stream can be used.
  • 31. MQTT con guration schema: mp.messaging.[outgoing|incoming]. {stream-name}.<property>=<value>. The connector type is smallrye-mqtt. mp.messaging.outgoing.topic-price.type= smallrye-mqtt mp.messaging.outgoing.topic-price.topic= prices mp.messaging.outgoing.topic-price.host= localhost mp.messaging.outgoing.topic-price.port= 1883 mp.messaging.outgoing.topic-price.auto-generated-client-id= true mp.messaging.incoming.prices.type= smallrye-mqtt mp.messaging.incoming.prices.topic= prices mp.messaging.incoming.prices.host= localhost mp.messaging.incoming.prices.port= 1883 mp.messaging.incoming.prices.auto-generated-client-id= true Kafka Streams Create streaming queries with the Kafka Streams API. ./mvnw quarkus:add-extension -Dextensions="kafka-streams" All we need to do for that is to declare a CDI producer method which returns the Kafka Streams org.apache.kafka.streams.Topology: @ApplicationScoped public class TopologyProducer { @Produces public Topology buildTopology() { org.apache.kafka.streams.StreamsBuilder.StreamsBuil der builder = new StreamsBuilder(); // ... builder.stream() .join() // ... .toStream() .to(); return builder.build(); } } Previous example produces content to another stream. If you want to write interactive queries, you can use Kafka streams. @Inject KafkaStreams streams; return streams .store("stream", QueryableStoreTypes.keyValueStore ()); The Kafka Streams extension is con gured via the Quarkus con guration le application.properties. quarkus.kafka-streams.bootstrap-servers=localhost:9092 quarkus.kafka-streams.application-id=temperature-aggregator quarkus.kafka-streams.application-server=${hostname}:8080 quarkus.kafka-streams.topics=weather-stations,temperature-v alues kafka-streams.cache.max.bytes.buffering=10240 kafka-streams.commit.interval.ms=1000 IMPORTANT: All the properties within the kafka-streams namespace are passed through as-is to the Kafka Streams engine. Changing their values requires a rebuild of the application. Reactive DataSource Properties Common Reeactive DataSource Client con guration properties pre xed with quarkus.datasource: reactive.cache-prepared-statements Prepared statements should be cached on the client side. (default: false) reactive.url The datasource URL. reactive.max-size The datasource pool maximum size. reactive.trust-all All server certi cates should be trusted. (default: false) reactive.trust-certificate-pem Trust con guration in the PEM format. reactive.trust-certificate-jks Trust con guration in the JKS format. reactive.trust-certificate-pfx Trust con guration in the PFX format. reactive.key-certificate-pem Key/cert con guration in the PEM format. reactive.key-certificate-jks Key/cert con guration in the JKS format. reactive.key-certificate-pfx Key/cert con guration in the PFX format. reactive.thread-local Use one connection pool per thread. reactive.reconnect-attempts The number of reconnection attempts when a pooled connection cannot be established on rst try. (default: 0) reactive.reconnect-interval The interval between reconnection attempts when a pooled connection cannot be established on rst try. (default: PT1S) reactive.idle-timeout The maximum time without data written to or read from a connection before it is removed from the pool. Reactive PostgreSQL Client You can use Reactive PostgreSQL to execute queries to PostreSQL database in a reactive way, instead of using JDBC way. ./mvnw quarkus:add-extension -Dextensions="quarkus-reactive-pg-client" Database con guration is the same as shown in Persistence section, but URL is different as it is not a jdbc. quarkus.datasource.db-kind=postgresql quarkus.datasource.reactive.url=postgresql:///your_database Then you can inject io.vertx.mutiny.pgclient.PgPool class. @Inject PgPool client; Uni<List<Fruit>> fruits = client.preparedQuery("SELECT * FROM fruits") .onItem().apply(rowSet -> { JsonArray jsonArray = new JsonArray(); for (Row row : rowSet) { jsonArray.add(from(row)); } return jsonArray; })
  • 32. Reactive MySQL Client You can use Reactive MySQL to execute queries to MySQL database in a reactive way, instead of using JDBC. ./mvnw quarkus:add-extension -Dextensions="quarkus-reactive-mysql-client" Database con guration is the same as shown in Persistence section, but URL is different as it is not a jdbc. quarkus.datasource.db-kind=mysql quarkus.datasource.reactive.url=mysql:///your_database Then you can inject io.vertx.mutiny.mysqlclient.MySQLPool class. Reactive DB2 Client You can use Reactive DB2 to execute queries to DB2 database in a reactive way, instead of using JDBC. ./mvnw quarkus:add-extension -Dextensions="quarkus-reactive-db2-client" Database con guration is the same as shown in Persistence section, but URL is different as it is not a jdbc. quarkus.datasource.db-kind=db2 quarkus.datasource.reactive.url=vertx-reactive:db2://localh ost:50005/hreact Then you can inject io.vertx.mutiny.db2client.DB2Pool class. Reactive Transactions io.vertx.mutiny.sqlclient.SqlClientHelper is an util class that allows you to run reactive persisten code within a transaction. Uni<Void> r = SqlClientHelper.inTransactionUni(client, tx - > { Uni<RowSet<Row>> insertOne = tx.preparedQuery("INSE RT INTO fruits (name) VALUES ($1) RETURNING (id)") .execute(Tuple.of(fruit1.name)); }); ActiveMQ Artemis Quarkus uses Reactive Messaging to integrate with messaging systems, but in case you need deeper control when using Apache ActiveMQ Artemis there is also an extension: ./mvnw quarkus:add-extension -Dextensions="quarkus-artemis-core" And then you can inject org.apache.activemq.artemis.api.core.client.ServerLocator instance. @ApplicationScoped public class ArtemisConsumerManager { @Inject ServerLocator serverLocator; private ClientSessionFactory connection; @PostConstruct public void init() throws Exception { connection = serverLocator.createSessionFactory(); } } And con gure ServerLocator in application.properties: quarkus.artemis.url=tcp://localhost:61616 You can con gure ActiveMQ Artemis in application.properties le by using next properties pre xed with quarkus: artemis.url Connection URL. artemis.username Username for authentication. artemis.password Password for authentication. Artemis JMS If you want to use JMS with Artemis, you can do it by using its extension: ./mvnw quarkus:add-extension -Dextensions="quarkus-artemis-jms" And then you can inject javax.jms.ConnectionFactory: @ApplicationScoped public class ArtemisConsumerManager { @Inject ConnectionFactory connectionFactory; private Connection connection; @PostConstruct public void init() throws JMSException { connection = connectionFactory.createConnection(); connection.start(); } } Con guration options are the same as Artemis core. Vert.X Reactive Clients Vert.X Reactive clients in Quarkus, the next clients are supported and you need to add the dependency to use them: Vert.X Mail Client io.smallrye.reactive:smallrye-mutiny-vertx-mail-client Vert.X MongoDB Client io.smallrye.reactive:smallrye-mutiny-vertx-mongo-client Vert.X Redis Client io.smallrye.reactive:smallrye-mutiny-vertx-redis-client Vert.X Cassandra Client io.smallrye.reactive:smallrye-mutiny-vertx-cassandra-client Vert.X Consul Client io.smallrye.reactive:smallrye-mutiny-vertx-consul-client Vert.X Kafka Client io.smallrye.reactive:smallrye-mutiny-vertx-kafka-client Vert.X AMQP Client io.smallrye.reactive:smallrye-mutiny-vertx-amqp-client Vert.X RabbitMQ Client io.smallrye.reactive:smallrye-mutiny-vertx-rabbitmq-client Example of Vert.X Web Client: @Inject Vertx vertx; private WebClient client; @PostConstruct void initialize() { this.client = WebClient.create(vertx, ...); }
  • 33. Amazon SQS Client ./mvnw quarkus:add-extension -Dextensions="amazon-sqs" Injecting the client: @Inject software.amazon.awssdk.services.sqs.SqsClient sqs; SendMessageResponse response = sqs.sendMessage(m -> m.queue Url(queueUrl).messageBody(message)); List<Message> messages = sqs.receiveMessage(m -> m.maxNumbe rOfMessages(10).queueUrl(queueUrl)).messages(); And con gure it: quarkus.sqs.endpoint-override=http://localhost:8010 quarkus.sqs.aws.region=us-east-1 quarkus.sqs.aws.credentials.type=static quarkus.sqs.aws.credentials.static-provider.access-key-id=t est-key quarkus.sqs.aws.credentials.static-provider.secret-access-k ey=test-secret You need to set a HTTP client either URL Connection: <dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>url-connection-client</artifactId> </dependency> or Apache HTTP: <dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>apache-client</artifactId> </dependency> quarkus.sqs.sync-client.type=apache You can go async by using Mutiny: @Inject software.amazon.awssdk.services.sqs.SqsAsyncClient sqs; Uni.createFrom() .completionStage( sqs.sendMessage(m -> m.queueUrl(queueUrl).messageBo dy(message)) ) .onItem()... return Uni.createFrom() .completionStage( sqs.receiveMessage(m -> m.maxNumberOfMessages(10).q ueueUrl(queueUrl)) ) .onItem() And you need to add the asynchronous Netty client: <dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>netty-nio-client</artifactId> </dependency> Con guration properties are the same as Amazon DynamoDB but changing the pre x from dynamodb to sqs. TLS You can trust all certi cates globally by using quarkus.tls.trust- all=true RBAC You can set RBAC using annotations or in application.properties. Annotations You can de ne roles by using javax.annotation.security.RolesAllowed annotation. @RolesAllowed("Subscriber") You can use io.quarkus.security.Authenticated as a shortcut of @RolesAllowed("*"). To alter RBAC behaviour there are two con guration properties: quarkus.security.deny-unannotated=true Con guration options: quarkus.jaxrs.deny-uncovered If true denies by default to all JAX-RS endpoints. (default: false) quarkus.security.deny-unannotated If true denies by default all CDI methods and JAX-RS endpoints. (default: false) By default in Quarkus, if an incoming request has a credential the request will always be authenticated (even if the target page does not require authentication). You can change this behaviour by setting quarkus.http.auth.proactive property to false. File Con guration De ning RBAC in application.properties instead of using annotations.
  • 34. quarkus.http.auth.policy.role-policy1.roles-allowed= user,admin quarkus.http.auth.permission.roles1.paths= /roles-secured/*,/other/*,/api/* quarkus.http.auth.permission.roles1.policy= role-policy1 quarkus.http.auth.permission.permit1.paths= /public/* quarkus.http.auth.permission.permit1.policy= permit quarkus.http.auth.permission.permit1.methods= GET quarkus.http.auth.permission.deny1.paths= /forbidden quarkus.http.auth.permission.deny1.policy= deny You need to provide permissions set by using the roles-allowed property or use the built-in ones deny, permit or authenticated. You can use enabled property (ie quarkus.http.auth.permission.permit1.enabled) to enable the entire permission set. Testing Quarkus provides explicit support for testing with different users, and with the security subsystem disabled. <dependency> <groupId>io.quarkus</groupId> <artifactId>quarkus-test-security</artifactId> <scope>test</scope> </dependency> @Test @TestSecurity(authorizationEnabled = false) void someTestMethod() { ... } @Test @TestSecurity(user = "testUser", roles = {"admin", "user"}) void someTestMethod() { ... } BouncyCastle Quarkus supports BouncyCastle, you only need to add the BouncyCastle dependency and con gure the security provider: quarkus.security.security-providers=BC quarkus.security.security-providers=BCJSSE quarkus.security.security-providers=BCFIPS quarkus.security.security-providers=BCFIPSJSSE JWT Quarkus implements MicroPro le JWT RBAC spec. mvn quarkus:add-extension -Dextensions="io.quarkus:quarkus-smallrye-jwt" Minimum JWT required claims: typ, alg, kid, iss, sub, exp, iat, jti, upn, groups. You can inject token by using JsonWebToken or a claim individually by using @Claim. @Inject JsonWebToken jwt; @Inject @Claim(standard = Claims.preferred_username) String name; @Inject @Claim("groups") Set<String> groups; @Inject JWTParser parser; Set of supported types: String, Set<String>, Long, Boolean, `javax.json.JsonValue, Optional, org.eclipse.microprofile.jwt.ClaimValue. And con guration in src/main/resources/application.properties: mp.jwt.verify.publickey.location= META-INF/resources/publicKey.pem mp.jwt.verify.issuer= https://quarkus.io/using-jwt-rbac Con guration options: mp.jwt.verify.publickey Public Key text itself to be supplied as a string. mp.jwt.verify.publickey.location Relative path or URL of a public key. mp.jwt.verify.issuer iss accepted as valid. smallrye.jwt.token.header Sets header such as Cookie is used to pass the token. (default: Authorization). smallrye.jwt.token.cookie Name of the cookie containing a token. smallrye.jwt.token.schemes Comma-separated list containing an alternative single or multiple schemes. (default: Bearer). smallrye.jwt.require.named-principal A token must have a upn or preferred_username or sub claim set if using java.security.Principal. True makes throw an exception if not set. (default: false). smallrye.jwt.path.sub Path to the claim with subject name. smallrye.jwt.claims.sub Default sub claim value. smallrye.jwt.path.groups Path to the claim containing the groups. smallrye.jwt.groups-separator Separator for splitting a string which may contain multiple group values. (default. ` `). smallrye.jwt.claims.groups Default groups claim value. smallrye.jwt.jwks.refresh-interval JWK cache refresh interval in minutes. (default: 60). smallrye.jwt.expiration.grace Expiration grace in seconds. (default: 60). smallrye.jwt.verify.aud Comma separated list of the audiences that a token aud claim may contain. smallrye.jwt.verify.algorithm Signature algorith. (defsult: RS256) smallrye.jwt.token.kid If set then the veri cation JWK key as well every JWT token must have a matching kid header. smallrye.jwt.time-to-live The maximum number of seconds that a JWT may be issued for use. smallrye.jwt.sign.key-location Location of a private key which will be used to sign the claims when either a no-argument sign() or innerSign() method is called. smallrye.jwt.encrypt.key-location
  • 35. Location of a public key which will be used to encrypt the claims or inner JWT when a no-argument encrypt() method is called. Supported public key formats: PKCS#8 PEM JWK JWKS JWK Base64 URL JWKS Base64 URL To send a token to server-side you should use Authorization header: curl -H "Authorization: Bearer eyJraWQiOi…". To inject claim values, the bean must be @RequestScoped CDI scoped. If you need to inject claim values in scope with a lifetime greater than @RequestScoped then you need to use javax.enterprise.inject.Instance interface. @Inject @Claim(standard = Claims.iat) private Instance<Long> providerIAT; RBAC JWT groups claim is directly mapped to roles to be used in security annotations. @RolesAllowed("Subscriber") Testing You can use @TestSecurity annotation tooin OIDC by registering the following dependency: <dependency> <groupId>io.quarkus</groupId> <artifactId>quarkus-test-security-jwt</artifactId> <scope>test</scope> </dependency> @Test @TestSecurity(user = "userJwt", roles = "viewer") @JwtSecurity(claims = { @Claim(key = "email", value = "user@gmail.com") }) public void testJwtWithClaims() {} Generate tokens JWT generation API: Jwt.claims() .issuer("https://server.com") .claim("customClaim", 3) .sign(createKey()); JwtSignatureBuilder jwtSignatureBuilder = Jwt.claims("/test JsonToken.json").jws(); jwtSignatureBuilder .signatureKeyId("some-key-id") .signatureAlgorithm(SignatureAlgorithm.ES256) .header("custom-header", "custom-value"); .sign(createKey()); Jwt.claims("/testJsonToken.json") .encrypt(createKey()); JwtEncryptionBuilder jwtEncryptionBuilder = Jwt.claims("/te stJsonToken.json").jwe(); jwtEncryptionBuilder .keyEncryptionKeyId("some-key-id") .keyEncryptionAlgorithm(KeyEncryptionAlgorithm.ECDH_E S_A256KW) .header("custom-header", "custom-value"); .encrypt(createKey()); Jwt.claims("/testJsonToken.json") .innerSign(createKey()); .encrypt(createKey()); OpenId Connect Quarkus can use OpenId Connect or OAuth 2.0 authorization servers such as Keycloak to protect resources using bearer token issued by Keycloak server. mvn quarkus:add-extension -Dextensions="using-openid-connect" You can also protect resources with security annotations. @GET @RolesAllowed("admin") You can inject the folowing Oidc objects in a class: @Inject io.quarkus.oidc.UserInfo userInfo; @Inject io.quarkus.oidc.OidcConfigurationMetadata configMetadata; Con gure application to Keycloak service in application.properties le. quarkus.oidc.realm=quarkus quarkus.oidc.auth-server-url=http://localhost:8180/auth quarkus.oidc.resource=backend-service quarkus.oidc.bearer-only=true quarkus.oidc.credentials.secret=secret quarkus-oidc-client can be con gured as follows to support MTLS: quarkus.oidc.tls.verification=certificate-validation quarkus.oidc.client.tls.key-store-file=client-keystore.jks quarkus.oidc.client.tls.key-store-password=${key-store-pass word} quarkus.oidc.client.tls.key-store-alias=keyAlias quarkus.oidc.client.tls.key-store-alias-password=keyAliasPa ssword quarkus.oidc.client.tls.trust-store-file=client-truststore. jks quarkus.oidc.client.tls.trust-store-password=${trust-store- password} quarkus.oidc.client.tls.trust-store-alias=certAlias There is also support for the public OIDC providers: GitHub quarkus.oidc.provider=github quarkus.oidc.client-id=github_app_clientid quarkus.oidc.credentials.secret=github_app_clientsecret Apple quarkus.oidc.provider=apple quarkus.oidc.client-id=${apple.client-id} quarkus.oidc.credentials.jwt.token-key-id=${apple.key-id} Google quarkus.oidc.provider=google quarkus.oidc.client-id={GOOGLE_CLIENT_ID} quarkus.oidc.credentials.secret={GOOGLE_CLIENT_SECRET} quarkus.oidc.token.issuer=https://accounts.google.com Con guration options with quarkus.oidc pre x: enabled The OIDC is enabled. (default: true) tenant-enabled If the tenant con guration is enabled. (default: true)
  • 36. The application type. Possible values: web_app, service. (default: service) connection-delay The maximum amount of time the adapter will try connecting. auth-server-url The base URL of the OpenID Connect (OIDC) server. introspection-path Relative path of the RFC7662 introspection service. jwks-path Relative path of the OIDC service returning a JWK set. public-key Public key for the local JWT token veri cation client-id The client-id of the application. roles.role-claim-path Path to the claim containing an array of groups. (realm/groups) roles.role-claim-separator Separator for splitting a string which may contain multiple group values. token.issuer Issuer claim value. token.audience Audience claim value. token.expiration-grace Expiration grace period in seconds. token.principal-claim Name of the claim which contains a principal name. token.refresh-expired If property is enabled then a refresh token request is performed. credentials.secret The client secret authentication.redirect-path Relative path for calculating a redirect_uri query parameter. authentication.restore-path-after-redirect The original request URI used before the authentication will be restored after the user has been redirected back to the application. (default: true) authentication.force-redirect-https-scheme Force 'https' as the 'redirect_uri' parameter scheme when running behind an SSL terminating reverse proxy. authentication.scopes List of scopes. authentication.extra-params Additional properties which will be added as the query parameters . authentication.cookie-path Cookie path parameter. proxy.host The host (name or IP address) of the Proxy. proxy.port The port number of the Proxy. (default: 80) proxy.username The username to authenticate. proxy.password The password to authenticate. end-session-path Relative path of the OIDC end_session_endpoint. logout.path The relative path of the logout endpoint at the application. logout.post-logout-path Relative path of the application endpoint where the user should be redirected to after logging out. tls.verification Sets the TLs veri cation. Possible values: REQUIRED, NONE. (default: REQUIRED). With Keycloak OIDC server https://host:port/auth/realms/{realm} where {realm} has to be replaced by the name of the Keycloak realm. You can use quarkus.http.cors property to enable consuming form different domain. Testing You can use @TestSecurity annotation tooin OIDC by registering the following dependency: <dependency> <groupId>io.quarkus</groupId> <artifactId>quarkus-test-security-oidc</artifactId> <scope>test</scope> </dependency> @Test @TestSecurity(user = "userOidc", roles = "viewer") @OidcSecurity(claims = { @Claim(key = "email", value = "user@gmail.com") }, userinfo = { @UserInfo(key = "sub", value = "subject") }, config = { @ConfigMetadata(key = "issuer", value = "issuer") }) public void testOidcWithClaimsUserInfoAndMetadata() {} DevServices When testing or running in dev mode Quarkus can even provide you with a zero con g Keycloak out of the box. Possible con guration values pre xed with quarkus.keycloak: devservices.enabled If devservices is enabled or not. (default: true) devservices.image-name The container image name to use instead of the default one. Keycloak-X can be used (quay.io/keycloak/keycloak-x:15.0.2) (default: quay.io/keycloak/keycloak:15.0.2) devservices.keycloak-x-image Set quarkus.devservices.keycloak.keycloak-x-image to override this check which may be necessary if you build custom Keycloak- X or Keycloak images. You do not need to set this property if the default check works. devservices.port Optional xed port the dev service will listen to. If not de ned, the port will be chosen randomly. devservices.shared Indicates if the Keycloak broker managed by Quarkus Dev Services is shared. When shared, Quarkus looks for running containers using label-based service discovery. (default: true) devservices.service-name The value of the quarkus-dev-service-keycloak label attached to the started container. (default: kafka) devservices.realm-path The class or le system path to a Keycloak realm le which will be used to initialize Keycloak devservices.java-opts The JAVA_OPTS passed to the keycloak JVM devservices.realm-name The Keycloak realm name devservices.create-realm Indicates if the Keycloak realm has to be created when the realm le pointed to by the 'realm-path' property does not exist
  • 37. devservices.users The Keycloak users map containing the user name and password pairs devservices.roles The Keycloak user roles Multi-tenancy Multi-tenancy is supported by adding a sub-category to OIDC con guration properties (ie quarkus.oidc.{tenent_id}.property). quarkus.oidc.auth-server-url=http://localhost:8180/auth/rea lms/quarkus quarkus.oidc.client-id=multi-tenant-client quarkus.oidc.application-type=web-app quarkus.oidc.tenant-b.auth-server-url=https://accounts.goog le.com quarkus.oidc.tenant-b.application-type=web-app quarkus.oidc.tenant-b.client-id=xxxx quarkus.oidc.tenant-b.credentials.secret=yyyy quarkus.oidc.tenant-b.token.issuer=https://accounts.google. com quarkus.oidc.tenant-b.authentication.scopes=email,profile,o penid You can inject io.quarkus.oidc.client.Tokens, io.quarkus.oidc.OidcSession, and io.quarkus.oidc.client.OidcClient to interact with OIDC. @Inject @io.quarkus.oidc.client.NamedOidcClient("client2") OidcClient client; @Inject @io.quarkus.oidc.client.NamedOidcClient("client1") Tokens tokens1; @Inject OidcSession oidcSession; OAuth2 Quarkus integrates with OAuth2 to be used in case of opaque tokens (none JWT) and its validation against an introspection endpoint. mvn quarkus:add-extension -Dextensions="security-oauth2" And con guration in src/main/resources/application.properties: quarkus.oauth2.client-id=client_id quarkus.oauth2.client-secret=secret quarkus.oauth2.introspection-url=http://oauth-server/intros pect And you can map roles to be used in security annotations. @RolesAllowed("Subscriber") Con guration options: quarkus.oauth2.enabled Determine if the OAuth2 extension is enabled. (default: true) quarkus.oauth2.client-id The OAuth2 client id used to validate the token. quarkus.oauth2.client-secret The OAuth2 client secret used to validate the token. quarkus.oauth2.introspection-url URL used to validate the token and gather the authentication claims. quarkus.oauth2.role-claim The claim that is used in the endpoint response to load the roles ((default: scope) Authenticating via HTTP HTTP basic auth is enabled by the quarkus.http.auth.basic=true property. HTTP form auth is enabled by the quarkus.http.auth.form.enabled=true property. Then you need to add elytron-security-properties-file or elytron- security-jdbc. Security with Properties File You can also protect endpoints and store identities (user, roles) in the le system. mvn quarkus:add-extension -Dextensions="elytron-security-properties-file" You need to con gure the extension with users and roles les: And con guration in src/main/resources/application.properties: quarkus.security.users.file.enabled=true quarkus.security.users.file.users=test-users.properties quarkus.security.users.file.roles=test-roles.properties quarkus.security.users.file.auth-mechanism=BASIC quarkus.security.users.file.realm-name=MyRealm quarkus.security.users.file.plain-text=true Then users.properties and roles.properties: scott=jb0ss jdoe=p4ssw0rd scott=Admin,admin,Tester,user jdoe=NoRolesUser IMPORTANT: If plain-text is set to false (or omitted) then passwords must be stored in the form MD5 (username:`realm`:`password`). Elytron File Properties con guration properties. Pre x quarkus.security.users is skipped. file.enabled The le realm is enabled. (default: false) file.auth-mechanism The authentication mechanism. ( default: BASIC) file.realm-name The authentication realm name. (default: Quarkus) file.plain-text If passwords are in plain or in MD5. (default: false) file.users Classpath resource of user/password. (default: users.properties) file.roles Classpath resource of user/role. (default: roles.properties) Embedded Realm You can embed user/password/role in the same application.properties: quarkus.security.users.embedded.enabled=true quarkus.security.users.embedded.plain-text=true quarkus.security.users.embedded.users.scott=jb0ss quarkus.security.users.embedded.roles.scott=admin,tester,us er quarkus.security.users.embedded.auth-mechanism=BASIC IMPORTANT: If plain-text is set to false (or omitted) then passwords must be stored in the form MD5 (username:`realm`:`password`). Pre x quarkus.security.users.embedded is skipped. algorithm Determine which algorithm to use. Possible values: DIGEST_MD5, DIGEST_SHA, DIGEST_SHA_256, DIGEST_SHA_384, DIGEST_SHA_512, DIGEST_SHA_512_256. (default: DIGEST_MD5) file.enabled
  • 38. The le realm is enabled. (default: false) file.auth-mechanism The authentication mechanism. (default: BASIC) file.realm-name The authentication realm name. (default: Quarkus) file.plain-text If passwords are in plain or in MD5. (default: false) file.users.* * is user and value is password. file.roles.* * is user and value is role. Security with a JDBC Realm You can also protect endpoints and store identities in a database. mvn quarkus:add-extension -Dextensions="elytron-security-jdbc" You still need to add the database driver (ie jdbc-h2). You need to con gure JDBC and Elytron JDBC Realm: quarkus.datasource.url= quarkus.datasource.driver=org.h2.Driver quarkus.datasource.username=sa quarkus.datasource.password=sa quarkus.security.jdbc.enabled=true quarkus.security.jdbc.principal-query.sql= SELECT u.password, u.role FROM test_user u WHERE u.user =? quarkus.security.jdbc.principal-query .clear-password-mapper.enabled=true quarkus.security.jdbc.principal-query .clear-password-mapper.password-index=1 quarkus.security.jdbc.principal-query .attribute-mappings.0.index=2 quarkus.security.jdbc.principal-query .attribute-mappings.0.to=groups You need to set the index (1-based) of password and role. Elytron JDBC Realm con guration properties. Pre x quarkus.security.jdbc is skipped. auth-mechanism The authentication mechanism. (default: BASIC) realm-name The authentication realm name. (default: Quarkus) bl d If the properties store is enabled. (default: false) principal-query.sql The sql query to nd the password. principal-query.datasource The data source to use. principal-query.clear-password-mapper.enabled If the clear-password-mapper is enabled. (default: false) principal-query.clear-password-mapper.password-index The index of column containing clear password. (default: 1) principal-query.bcrypt-password-mapper.enabled If the bcrypt-password-mapper is enabled. (default: false) principal-query.bcrypt-password-mapper.password-index The index of column containing password hash. (default: 0) principal-query.bcrypt-password-mapper.hash-encoding A string referencing the password hash encoding (BASE64 or HEX). (default: BASE64) principal-query.bcrypt-password-mapper.salt-index The index column containing the Bcrypt salt. (default: 0) principal-query.bcrypt-password-mapper.salt-encoding A string referencing the salt encoding (BASE64 or HEX). (default: BASE64) principal-query.bcrypt-password-mapper.iteration-count-index The index column containing the Bcrypt iteration count. (default: 0) For multiple datasources you can use the datasource name in the properties: quarkus.datasource.url= quarkus.security.jdbc.principal-query.sql= quarkus.datasource.permissions.url= quarkus.security.jdbc.principal-query.permissions.sql= Security with JPA You can also protect endpoints and store identities in a database using JPA. mvn quarkus:add-extension -Dextensions="security-jpa" Also you might require jdbc-postgresql, resteasy, hibernate-orm-panache. @io.quarkus.security.jpa.UserDefinition @Table(name = "test_user") @Entity public class User extends PanacheEntity { @io.quarkus.security.Username public String name; @io.quarkus.security.Password public String pass; @ManyToMany @Roles public List<Role> roles = new ArrayList<>(); public static void add(String username, String passwor d) { User user = new User(); user.username = username; user.password = BcryptUtil.bcryptHash(password); user.persist(); } } @Entity public class Role extends PanacheEntity { @ManyToMany(mappedBy = "roles") public List<ExternalRolesUserEntity> users; @io.quarkus.security.RolesValue public String role; } You need to con gure JDBC: quarkus.datasource.url=jdbc:postgresql:security_jpa quarkus.datasource.driver=org.postgresql.Driver quarkus.datasource.username=quarkus quarkus.datasource.password=quarkus quarkus.hibernate-orm.database.generation=drop-and-create Security with LDAP You can also protect endpoints and store identities in a database using LDAP. mvn quarkus:add-extension -Dextensions="elytron-security-ldap"
  • 39. quarkus.security.ldap.enabled=true quarkus.security.ldap.dir-context.principal=uid=tool,ou=acc ounts,o=YourCompany,c=DE quarkus.security.ldap.dir-context.url=ldaps://ldap.server.l ocal quarkus.security.ldap.dir-context.password=PASSWORD quarkus.security.ldap.identity-mapping.rdn-identifier=uid quarkus.security.ldap.identity-mapping.search-base-dn=ou=us ers,ou=tool,o=YourCompany,c=DE quarkus.security.ldap.identity-mapping.attribute-mapping s."0".from=cn quarkus.security.ldap.identity-mapping.attribute-mapping s."0".to=groups quarkus.security.ldap.identity-mapping.attribute-mapping s."0".filter=(member=uid={0}) quarkus.security.ldap.identity-mapping.attribute-mapping s."0".filter-base-dn=ou=roles,ou=tool,o=YourCompany,c=DE Testing There is a Quarkus Test Resource that starts and stops InMemory LDAP server before and after test suite. It is running in localhost with dc=quarkus,dc=io and binding credentials ("uid=admin,ou=system", "secret"). Imports LDIF from a le located at root of the classpath named quarkus-io.ldif. Register dependency io.quarkus:quarkus-test-ldap:test. And annotate the test: @QuarkusTestResource(io.quarkus.test.ldap.LdapServerTestRes ource.class) public class ElytronLdapExtensionTestResources { } Elytron LDAP Realm con guration properties. Pre x quarkus.security.ldap is skipped. enabled Enable the LDAP elytron module (default: false) realm-name The elytron realm name (default: Quarkus) direct-verification Provided credentials are veri ed against LDAP (default: true) dir-context.url The url of the LDAP server. dir-context.principal User (bindDn) which is used to connect to LDAP server. dir-context.password The password (bindCredential) which belongs to the principal. identity-mapping.rdn-identifier The identi er (baseFilter) which correlates to the provided user (default: uid) identity-mapping.search-base-dn The dn where we look for users. identity-mapping.attribute-mappings.<id>.from The roleAttributeId from which is mapped identity-mapping.attribute-mappings.<id>.to The identi er whom the attribute is mapped to (default: gropus) identity-mapping.attribute-mappings.<id>.filter The lter (roleFilter) identity-mapping.attribute-mappings.<id>.filter-base-dn The lter base dn (rolesContextDn) Vault Quarkus integrates with Vault to manage secrets or protecting sensitive data. mvn quarkus:add-extension -Dextensions="vault" And con guring Vault in application.properties: # vault url quarkus.vault.url=http://localhost:8200 quarkus.vault.authentication.userpass.username= bob quarkus.vault.authentication.userpass.password= sinclair # path within the kv secret engine quarkus.vault.secret-config-kv-path= myapps/vault-quickstart/config quarkus.vault.secret-config-kv-prefix.singer.paths= multi/singer1, multi/singer2 vault kv put secret/myapps/vault-quickstart/config a-private- key=123456 vault kv put secret/multi/singer1 firstname=paul @ConfigProperty(name = "a-private-key") String privateKey; @ConfigProperty(name = "singer.firstname") String firstName; You can access the KV engine programmatically: @Inject VaultKVSecretEngine kvSecretEngine; kvSecretEngine.readSecret("myapps/vault-quickstart/" + vaul tPath).toString(); Map<String, String> secrets; kvSecretEngine.writeSecret("myapps/vault-quickstart/crud", secrets); kvSecretEngine.deleteSecret("myapps/vault-quickstart/crud" ); Fetching credentials DB With the next kv vault kv put secret/myapps/vault-quickstart/db password=connor quarkus.vault.credentials-provider.mydatabase.kv-path= myapps/vault-quickstart/db quarkus.datasource.db-kind= postgresql quarkus.datasource.username= sarah quarkus.datasource.credentials-provider= mydatabase quarkus.datasource.jdbc.url= jdbc:postgresql://localhost:5432/mydatabase No password is set as it is fetched from Vault. Dynamic credentials are also supported: Running the following dynamic database con g in Vault: vault write database/config/mydb plugin_name=postgresql-database- plugin ….. You can con gure as: quarkus.vault.credentials-provider .mydatabase.database-credentials-role=mydbrole quarkus.datasource.db-kind= postgresql quarkus.datasource.credentials-provider= mydatabase quarkus.datasource.jdbc.url= jdbc:postgresql://localhost:5432/mydatabase Username and password are fetched from Vault Transit
  • 40. @Inject VaultTransitSecretEngine transit; transit.encrypt("my_encryption", text); transit.decrypt("my_encryption", text).asString(); transit.sign("my-sign-key", text); Transit Key @Inject VaultTransitSecretEngine transit; transit.createKey(KEY_NAME, new KeyCreationRequestDetail(). setExportable(true)); transit.readKey(KEY_NAME); transit.listKeys(); transit.exportKey(KEY_NAME, VaultTransitExportKeyType.encry ption, null); transit.updateKeyConfiguration(KEY_NAME, new KeyConfigReque stDetail().setDeletionAllowed(true)); transit.deleteKey(KEY_NAME); Vault TOTP TOTP secret engine is supported by using io.quarkus.vault.VaultTOTPSecretEngine class: @Inject VaultTOTPSecretEngine vaultTOTPSecretEngine; CreateKeyParameters createKeyParameters = new CreateKeyPara meters("Google", "test@gmail.com"); createKeyParameters.setPeriod("30m"); /** Generate Key (QR code) */ final Optional<KeyDefinition> myKey = vaultTOTPSecretEngine .createKey("my_ key_2", createKeyParameters); /** Generate key number to login */ final String keyCode = vaultTOTPSecretEngine.generateCode( "my_key_2"); /** Login logic */ boolean valid = vaultTOTPSecretEngine.validateCode("my_key_ 2", keyCode); Vault Provisioning Vault extension offers façade classes to Vault provisioning functions: @Inject VaultSystemBackendEngine vaultSystemBackendEngine; @Inject VaultKubernetesAuthService vaultKubernetesAuthService; String rules = "path "transit/*" {n" + " capabilities = [ "create", "read", "updat e" ]n" + "}"; String policyName = "sys-test-policy"; vaultSystemBackendEngine.createUpdatePolicy(policyName, rul es); vaultKubernetesAuthService .createRole(roleName, new VaultKubernetesAuthRole() .setBoundServiceAccountNames(boundServiceAccountN ames) .setBoundServiceAccountNamespaces(boundServiceAcc ountNamespaces) .setTokenPolicies(tokenPolicies)); PKI @Inject public VaultPKISecretEngine pkiSecretEngine; GenerateCertificateOptions options = new GenerateCertificat eOptions(); SignedCertificate signed = pkiSecretEngine.signRequest( "example-dot-com", csr, options); return signed.certificate.getData(); Vault con guration properties. Pre x quarkus.vault is skipped. url Vault server URL authentication.client-token Vault token to access authentication.app-role.role-id Role Id for AppRole auth authentication.app-role.secret-id Secret Id for AppRole auth authentication.app-role.secret-id-wrapping-token Wrapping token containing a Secret Id. secret-id and secret-id- wrapping-token are exclusive. authentication.userpass.username Username for userpass auth authentication.userpass.password Password for userpass auth authentication.userpass.password-wrapping-token Wrapping token containing a password. password and password- wrapping-token are exclusive. authentication.kubernetes.role Kubernetes authentication role authentication.kubernetes.jwt-token-path Location of the le containing the Kubernetes JWT token renew-grace-period Renew grace period duration (default: 1H) secret-config-cache-period Vault con g source cache period (default: 10M) secret-config-kv-path Vault path in kv store. List of paths is supported in CSV log-confidentiality-level Used to hide con dential infos. low, medium, high (default: medium) kv-secret-engine-version Kv secret engine version (default: 1) kv-secret-engine-mount-path Kv secret engine path (default: secret) tls.skip-verify Allows to bypass certi cate validation on TLS communications (default: false) tls.ca-cert Certi cate bundle used to validate TLS communications tls.use-kubernetes-ca-cert TLS will be active (default: true) connect-timeout Tiemout to establish a connection (default: 5S) read-timeout Request timeout (default: 1S) credentials-provider."credentials-provider".database-credentials- role Database credentials role credentials-provider."credentials-provider".kv-path A path in vault kv store, where we will nd the kv-key credentials-provider."credentials-provider".kv-key Key name to search in vault path kv-path (default: password) DevServices When testing or running in dev mode Quarkus can even provide you with a zero con g Vault out of the box.
  • 41. Possible con guration values are shown at Vault Amazon KMS mvn quarkus:add-extension -Dextensions="amazon-kms" @Inject KmsClient kms; kms.encrypt(req -> req.keyId(keyArn).plaintext( SdkBytes.fromUtf8String(data))).ciphertextBlob(); quarkus.kms.endpoint-override=http://localhost:8011 quarkus.kms.aws.region=us-east-1 quarkus.kms.aws.credentials.type=static quarkus.kms.aws.credentials.static-provider.access-key-id=t est-key quarkus.kms.aws.credentials.static-provider.secret-access-k ey=test-secret You need to set a HTTP client either URL Connection: <dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>url-connection-client</artifactId> </dependency> or Apache HTTP: <dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>apache-client</artifactId> </dependency> quarkus.sqs.sync-client.type=apache You can go async by using Mutiny: @Inject software.amazon.awssdk.services.kms.KmsAsyncClient kms; Uni.createFrom().completionStage( kms.encrypt(req -> req.keyId(keyArn).plaintext(SdkByte s.fromUtf8String(data)) )) And you need to add the asynchronous Netty client: <dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>netty-nio-client</artifactId> </dependency> Con guration properties are the same as Amazon DynamoDB but changing the pre x from dynamodb to kms. Amazon IAM mvn quarkus:add-extension -Dextensions="quarkus-amazon-iam" You need to set a HTTP client either URL Connection: <dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>url-connection-client</artifactId> </dependency> or Apache HTTP: <dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>apache-client</artifactId> </dependency> And you need to add the asynchronous Netty client: <dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>netty-nio-client</artifactId> </dependency> @Inject IamClient client; @Inject IamAsyncClient async; quarkus.iam.endpoint-override=${iam.url} quarkus.iam.aws.region=us-east-1 quarkus.iam.aws.credentials.type=static quarkus.iam.aws.credentials.static-provider.access-key-id=t est-key quarkus.iam.aws.credentials.static-provider.secret-access-k ey=test-secret Con guration properties are the same as Amazon DynamoDB but changing the pre x from dynamodb to iam. HTTP Con guration You can con gure HTTP parameters. Using quarkus.http pre x: http.access-log.exclude-pattern A regular expression that can be used to exclude some paths from logging cors Enable CORS. (default: false) cors.origins CSV of origins allowed. Regular expressions are also allowed (dedault: Any request valid.) cors.methods CSV of methods valid. (default: Any method valid.) cors.headers CSV of valid allowed headers. (default: Any requested header valid.) cors.exposed-headers CSV of valid exposed headers. port The HTTP port. (default: 8080) test-port The HTTP test port. (default: 8081) host The HTTP host. (default: 0.0.0.0) host-enabled Enable listening to host:port. (default: true) ssl-port The HTTPS port. (default 8443) test-ssl-port The HTTPS port used to run tests. (default: 8444) insecure-requests If insecure requests are allowed. Possible values: enabled, redirect, disable. (default: enabled) http2 Enables HTTP/2. (default: true) proxy.proxy-address-forwarding The address, scheme etc will be set from headers forwarded by the proxy server. proxy.allow-forwarded Proxy address forwarding is enabled then the standard Forwarded header will be used, rather than the more common but not standard X-Forwarded-For
  • 42. proxy.enable-forwarded-host Enable override the received request’s host through a forwarded host header proxy.forwarded-host-header Con gure the forwarded host header to be used if override enabled ssl.port The HTTPS port. (default: 8443) ssl.certificate.files The les path to a service certi cate or certi cate chain in PEM format. Relative to src/main/resources. ssl.certificate.key-files The les path to the corresponding certi cate private key in PEM format. Relative to src/main/resources. ssl.certificate.key-store-file The key store contains the certi cate information. Relative to src/main/resources. ssl.certificate.key-store-key-alias An optional parameter to select a speci c key in the key store. ssl.certificate.key-store-file-type The key store type. It is automatically detected based on the le name or can be set manually. Supported values are: JKS, JCEKS, P12, PKCS12 or PFX. ssl.certificate.key-store-password The password to open the key store le. ssl.certificate.trust-store-file The trust store location which contains the certi cate information of the certi cates to trust. Relative to src/main/resources. ssl.certificate.trust-store-cert-alias An optional parameter to trust only one speci c certi cate in the trust store ssl.certificate.trust-store-file-type The trust store type. It is automatically detected based on the le name or can be set manually. ssl.certificate.trust-store-password The password to open the trust store le. ssl.cipher-suites A list of strings of cipher suites to use. If not provided, a reasonable default is selected. ssl.protocols The list of protocols to explicitly enable. (default: TLSv1.3 and TLSv1.2). Enables Server Name Indication (SNI), an TLS extension allowing the server to use multiple certi cates. (default: false) ssl.client-auth Con gures the engine to require/request client authentication. Possible values are: none, request and required. (default: none). io-threads The number if IO threads used to perform IO. limits.max-header-size The maximum length of all headers. (default: 20k) limits.max-body-size The maximum size of a request body. (default: 10M) limits.max-chunk-size The max HTTP chunk size. limits.max-initial-line-length The maximum length of the initial line. (default: 4096) idle-timeout Http connection idle timeout. (default: 30M) enable-compression If responses should be compressed. read-timeout Http connection read timeout for blocking IO. (default: 60s) body.handle-file-uploads If the les sent using multipart/form-data will be stored locally. (default: true) body.uploads-directory The directory where the les sent using multipart/form-data should be stored. (default: file-uploads) body.merge-from-attributes If the form attributes should be added to the request parameters. (default: true) body.delete-uploaded-files-on-end If the uploaded les should be removed after serving the request. body.preallocate-body-buffer If the body buffer should pre-allocated based on the Content- Length header value. (default: 1K) auth.session.encryption-key The encryption key that is used to store persistent logins. so-reuse-port Enable socket reuse port. tcp-quick-ack Enable tcp quick ack tcp-cork Enable tcp cork. tcp-fast-open Enable tcp fast open. domain-socket Path to a unix domain socket. (default: /var/run/io.quarkus.app.socket) domain-socket-enabled Enables domain socket. record-request-start-time If enabled then start time will be recorded to enable logging of total request time. (default: false) access-log.enabled If access logging is enabled. (default: false) access-log.pattern The access log pattern. (default: common) access-log.log-to-file If logging should be done to a separate le. (default: false) access-log.base-file-name The access log le base name. (default: quarkus) access-log.log-directory The log directory to use when logging access to a le. access-log.log-directory The log directory to use when logging access to a le. access-log.log-suffix The log le su x. (default: .log) access-log.category The log category to use if logging is being done via the standard log mechanism. (default: io.quarkus.http.access-log) access-log.rotate If the log should be rotated daily. (default: true) same-site-cookie.<name>.case-sensitive If the cookie pattern is case sensitive. same-site-cookie.<name>.value The value to set in the samesite attribute. same-site-cookie.<name>.enable-client-checker Some User Agents break when sent SameSite=None, this will detect them and avoid sending the value. (default: true) same-site-cookie.<name>.add-secure-for-none If this is true then the 'secure' attribute will automatically be sent k h b f (d f l )
  • 43. If metrics extension is registered, you can enable to get HTTP metrics by setting quarkus.resteasy.metrics.enabled to true. JAX-RS Quarkus uses JAX-RS to de ne REST-ful web APIs. Under the covers, Rest-EASY is working with Vert.X directly without using any Servlet. It is important to know that if you want to use any feature that implies a Servlet (ie Servlet Filters) then you need to add the quarkus-undertow extension to switch back to the Servlet ecosystem but generally speaking, you don’t need to add it as everything else is well-supported. @Path("/book") public class BookResource { @GET @Produces(MediaType.APPLICATION_JSON) public List<Book> getAllBooks() {} @POST @Produces(MediaType.APPLICATION_JSON) public Response createBook(Book book) {} @DELETE @Path("{isbn}") @Produces(MediaType.APPLICATION_JSON) public Response deleteBook( @PathParam("isbn") String isbn) {} @GET @Produces(MediaType.APPLICATION_JSON) @Path("search") public Response searchBook( @QueryParam("description") String description) {} } To get information from request: @PathParam Gets content from request URI. (example: /book/{id} @PathParam("id")) @QueryParam Gets query parameter. (example: /book?desc="" @QueryParam("desc)) @FormParam Gets form parameter. @MatrixParam Get URI matrix parameter. (example: /book;author=mkyong;country=malaysia) @CookieParam Gets cookie param by name. @HeaderParam Gets header parameter by name. Valid HTTP method annotations provided by the spec are: @GET, @POST, @PUT, @DELETE, @PATCH, @HEAD and @OPTIONS. You can create new annotations that bind to HTTP methods not de ned by the spec. @Target({ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @HttpMethod("LOCK") public @interface LOCK { } @LOCK public void lockIt() {} } Injecting Using @Context annotation to inject JAX-RS and Servlet information. @GET public String getBase(@Context UriInfo uriInfo) { return uriInfo.getBaseUri(); } Possible injectable objects: SecurityContext, Request, Application, Configuration, Providers, ResourceContext, ServletConfig, ServletContext, HttpServletRequest, HttpServletResponse, HttpHeaders, Urinfo, SseEventSink and Sse. HTTP Filters HTTP request and response can be intercepted to manipulate the metadata (ie headers, parameters, media type, …) or abort a request. You only need to implement the next ContainerRequestFilter and ContainerResponseFilter JAX-RS interfaces respectively. @Provider public class LoggingFilter implements ContainerRequestFilter { @Context UriInfo info; @Context HttpServletRequest request; @Override public void filter(ContainerRequestContext context) { final String method = context.getMethod(); final String path = info.getPath(); final String address = request.getRemoteAddr(); System.out.println("Request %s %s from IP %s", method, path, address); } } Exception Mapper You can map exceptions to produce a custom output by implementing ExceptionMapper interface: @Provider public class ErrorMapper implements ExceptionMapper<Exception> { @Override public Response toResponse(Exception exception) { int code = 500; if (exception instanceof WebApplicationException) { code = ((WebApplicationException) exception) .getResponse().getStatus(); } return Response.status(code) .entity( Json.createObjectBuilder() .add("error", exception.getMessage()) .add("code", code) .build() ) .build(); } } Caching Annotations to set Cache-Control headers:
  • 44. @Produces(MediaType.APPLICATION_JSON) @org.jboss.resteasy.annotations.cache.NoCache public User me() {} @Produces(MediaType.APPLICATION_JSON) @org.jboss.resteasy.annotations.cache.Cache( maxAge = 2000, noStore = false ) public User you() {} Vert.X Filters and Routes Programmatically You can also register Vert.X Filters and Router programmatically inside a CDI bean: import io.quarkus.vertx.http.runtime.filters.Filters; import io.vertx.ext.web.Router; import javax.enterprise.context.ApplicationScoped; import javax.enterprise.event.Observes; @ApplicationScoped public class MyBean { public void filters( @Observes Filters filters) { filters .register( rc -> { rc.response() .putHeader("X-Filter", "filter 1"); rc.next(); }, 10); } public void routes( @Observes Router router) { router .get("/") .handler(rc -> rc.response().end("OK")); } } Declarative You can use @Route annotation to use reactive routes and @RouteFilter to sue reactive lters in a declarative way: ./mvnw quarkus:add-extension -Dextensions="quarkus-vertx-web" @ApplicationScoped public class MyDeclarativeRoutes { @Route(path = "/hello", methods = HttpMethod.GET) public void greetings(RoutingContext rc) { String name = rc.request().getParam("name"); if (name == null) { name = "world"; } rc.response().end("hello " + name); } @RouteFilter(20) void filter(RoutingContext rc) { rc.response().putHeader("X-Filter", "filter 2"); rc.next(); } @Route String hello(@Param Optional<String> name) {} @Route String helloFromHeader(@Header("My-Header") String head er) {} @Route String createPerson(@Body Person person) {} } GraphQL Quarkus integrates with GraphQL using MicroPro le GraphQL integration. ./mvnw quarkus:add-extension -Dextensions="graphql" @GraphQLApi public class FilmResource { @Query("allFilms") public List<String> films() { } @Query public String getFilm(@Name("filmId") int id)) {} @Query public List<Hero> getHeroesWithSurname( @DefaultValue("Skywalker") String surname) { } @Mutation public Greetings load(Greetings greetings) { } } If name not provided, then query name is resolved from method name. You can see the full schema at /graphql/schema.graphql. Also GraphiQL UI is enabled at dev and test mode at /graphql-ui/. Extension can be con gured with the follwoing paramters pre xed with quarkus.smallrye-graphql. root-path The rootPath under which queries will be served. (default: /graphql) root-path-ui The path where GraphQL UI is available. (default: /graphql-ui) always-include-ui The path where GraphQL UI is available. (default: /graphql-ui) root-path-ui Always include the UI. By default this will only be included in dev and test. (default: false) enable-ui If GraphQL UI should be enabled. (default: false) schema-available Make the schema available over HTTP. (default: true) metrics.enabled Enable metrics. (default: false) GraphQL Clients ./mvnw quarkus:add-extension -Dextensions="graphql-client" quarkus.smallrye-graphql-client.star-wars.url=https://swapi -graphql.netlify.app/.netlify/functions/index Typesafe client @GraphQLClientApi(configKey = "star-wars") public interface StarWarsClientApi { FilmConnection allFilms(); } @Inject StarWarsClientApi typesafeClient; allFilms is also the name of the query. You can override the value using @Query(value="allStarWarsFilms") Dynamic client
  • 45. @Inject @GraphQLClient("star-wars") DynamicGraphQLClient dynamicClient; Document query = document( operation( field("allFilms", field("films", field("title"), field("planetConnection", field("planets", field("name") ) ) ) ) ) ); Response response = dynamicClient.executeSync(query) Vert.X Verticle Vert.X Verticles are also supported: @ApplicationScoped public class VerticleDeployer { @Inject Vertx vertx; public void init(@Observes StartupEvent ev) { CountDownLatch latch = new CountDownLatch(1); vertx.deployVerticle(BareVerticle::new, new DeploymentOptions() .setConfig( new JsonObject() .put("id", "bare") ) ) .thenAccept(x -> latch.countDown()); latch.countDown(); } } Verticles can be: bare extending io.vertx.core.AbstractVerticle. mutiny extendig io.smallrye.mutiny.vertx.core.AbstractVerticle. GZip Support You can con gure Quarkus to use GZip in the application.properties le using the next properties with quarkus.resteasy su x: gzip.enabled EnableGZip. (default: false) gzip.max-input Con gure the upper limit on de ated request body. (default: 10M) GRPC Quarkus integrates with gRPC: ./mvnw quarkus:add-extension -Dextensions="quarkus-grpc" Then you need to con gure build tool with gRPC plugins. In the case of Maven, the kr.motd.maven:os-maven-plugin extension and org.xolstice.maven.plugins:protobuf-maven-plugin Protos les are stored at src/main/proto. When java les are created two service implementations are provided: one with default gRPC API and other with Mutiny support. With quarkus.grpc.server pre x, the next con guration properties can be set: port The gRPC Server port. (default: 9000) host The gRPC server host. (default: 0.0.0.0) handshake-timeout The gRPC handshake timeout. max-inbound-message-size The max inbound message size in bytes. plain-text Use plain text. (default: true) alpn TWhether ALPN should be used. (default: true) enable-reflection-service Enables the gRPC Re ection Service. (default: false) ssl.certificate The le path to a server certi cate or certi cate chain in PEM format. ssl.key The le path to the corresponding certi cate private key le in PEM format. ssl.key-store An optional key store which holds the certi cate information instead of specifying separate les. ssl.key-store-type An optional parameter to specify the type of the key store le. ssl.key-store-password A parameter to specify the password of the key store le. (default: password) ssl.trust-store Trust store which holds the certi cate information of the certi cates to trust ssl.trust-store-type Parameter to specify type of the trust store le. ssl.trust-store-password A parameter to specify the password of the trust store le. ssl.cipher-suites A list of the cipher suites to use. ssl.protocols The list of protocols to explicitly enable. (default: TLSv1.3,TLSv1.2) transport-security.certificate The path to the certi cate le. transport-security.key The path to the private key le. load-balancing-policy Use a custom load balancing policy. Possible values: pick_first, round_robin, grpclb. (default: pick_first) To consume the service: @GrpcClient("hello") GreeterGrpc.GreeterBlockingStub client; @GrpcClient("hello") io.grpc.Channel channel; // Adding headers Metadata extraHeaders = new Metadata(); extraHeaders.put("my-header", "my-interface-value"); GreeterBlockingStub alteredClient = io.quarkus.grpc.GrpcCli entUtils.attachHeaders(client, extraHeaders); Interceptors
  • 46. import io.quarkus.grpc.GlobalInterceptor; import io.grpc.ClientInterceptor; @GlobalInterceptor @ApplicationScoped public class MyInterceptor implements ClientInterceptor {} @RegisterClientInterceptor(MySpecialInterceptor.class) (1) @GrpcClient("helloService") Greeter greeter; Some con guration example to set the host and the SSL parameters: quarkus.grpc.clients.hello.host=localhost quarkus.grpc.clients.hello.plain-text=false quarkus.grpc.clients.hello.ssl.certificate=src/main/resourc es/tls/client.pem quarkus.grpc.clients.hello.ssl.key=src/main/resources/tls/c lient.key quarkus.grpc.clients.hello.ssl.trust-store=src/main/resourc es/tls/ca.pem Smallrye Stork Stork implements client load-balancing strategies supporting Kubernetes, and Consul. Consul Add following dependencies: <dependency> <groupId>io.smallrye.stork</groupId> <artifactId>stork-service-discovery-consul</artifactId> </dependency> <dependency> <groupId>io.smallrye.reactive</groupId> <artifactId>smallrye-mutiny-vertx-consul-client</artifact Id> </dependency> Register service instances to Consul: @ApplicationScoped public class Registration { @ConfigProperty(name = "consul.host") String host; @ConfigProperty(name = "consul.port") int port; public void init(@Observes StartupEvent ev, Vertx vert x) { ConsulClient client = ConsulClient.create(vertx, new ConsulClientOptions().s etHost(host).setPort(port)); client.registerServiceAndAwait( new ServiceOptions().setPort(8080) .setAddress("host1").setName("my-servic e").setId("blue")); client.registerServiceAndAwait( new ServiceOptions().setPort(8080) .setAddress("host2").setName("my-servic e").setId("red")); } } Con guration: consul.host=localhost consul.port=8500 stork.my-service.service-discovery=consul stork.my-service.service-discovery.consul-host=localhost stork.my-service.service-discovery.consul-port=8500 stork.my-service.load-balancer=round-robin Kubernetes Add following dependencies: <dependency> <groupId>io.smallrye.reactive</groupId> <artifactId>stork-service-discovery-kubernetes</artifactI d> </dependency> stork.my-service.service-discovery=kubernetes stork.my-service.service-discovery.k8s-namespace=my-namespa ce stork.my-service.load-balancer=round-robin Using Stork at client @RegisterRestClient(baseUri = "stork://my-service") public interface MyService { @GET @Produces(MediaType.TEXT_PLAIN) String get(); } Fault Tolerance Quarkus uses MicroPro le Fault Tolerance spec: ./mvnw quarkus:add-extension -Dextensions="io.quarkus:quarkus-smallrye-fault-toleranc e" MicroPro le Fault Tolerance spec uses CDI interceptor and it can be used in several elements such as CDI bean, JAX-RS resource or MicroPro le Rest Client. To do automatic retries on a method: @Path("/api") @RegisterRestClient public interface WorldClockService { @GET @Path("/json/cet/now") @Produces(MediaType.APPLICATION_JSON) @Retry(maxRetries = 2) WorldClock getNow(); } You can set fallback code in case of an error by using @Fallback annotation: @Retry(maxRetries = 1) @Fallback(fallbackMethod = "fallbackMethod") WorldClock getNow(){} public WorldClock fallbackMethod() { return new WorldClock(); } fallbackMethod must have the same parameters and return type as the annotated method. You can also set logic into a class that implements FallbackHandler interface: public class RecoverFallback implements FallbackHandler<WorldClock> { @Override public WorldClock handle(ExecutionContext context) { } }
  • 47. And set it in the annotation as value @Fallback(RecoverFallback.class). In case you want to use circuit breaker pattern: @CircuitBreaker(requestVolumeThreshold = 4, failureRatio=0.75, delay = 1000) WorldClock getNow(){} If 3 (4 x 0.75) failures occur among the rolling window of 4 consecutive invocations then the circuit is opened for 1000 ms and then be back to half open. If the invocation succeeds then the circuit is back to closed again. You can use bulkahead pattern to limit the number of concurrent access to the same resource. If the operation is synchronous it uses a semaphore approach, if it is asynchronous a thread-pool one. When a request cannot be processed BulkheadException is thrown. It can be used together with any other fault tolerance annotation. @Bulkhead(5) @Retry(maxRetries = 4, delay = 1000, retryOn = BulkheadException.class) WorldClock getNow(){} From smallrye project Fibonacci and Exponential Backoff retries annotations are provided: public class TwoBackoffsOnMethodService { @Retry @io.smallrye.faulttolerance.api.ExponentialBackoff @io.smallrye.faulttolerance.api.FibonacciBackoff public void hello() { throw new IllegalArgumentException(); } } Fault tolerance annotations: Annotation Properties @Timeout unit @Retry maxRetries, delay, delayUnit, maxDuration, durationUnit, jitter, jitterDelayUnit, retryOn, abortOn @Fallback fallbackMethod @Bulkhead waitingTaskQueue (only valid in asynchronous) Annotation Properties @CircuitBreaker failOn, delay, delayUnit, requestVolumeThreshold, failureRatio, successThreshold @Asynchronous You can override annotation parameters via con guration le using property [classname/methodname/]annotation/parameter: org.acme.quickstart.WorldClock/getNow/Retry/maxDuration=30 # Class scope org.acme.quickstart.WorldClock/Retry/maxDuration=3000 # Global Retry/maxDuration=3000 You can also enable/disable policies using special parameter enabled. org.acme.quickstart.WorldClock/getNow/Retry/enabled=false # Disable everything except fallback MP_Fault_Tolerance_NonFallback_Enabled=false MicroPro le Fault Tolerance integrates with MicroPro le Metrics spec. You can disable it by setting MP_Fault_Tolerance_Metrics_Enabled to false. Observability Health Checks Quarkus relies on MicroPro le Health spec to provide health checks. ./mvnw quarkus:add-extension -Dextensions="io.quarkus:quarkus-smallrye-health" By just adding this extension, an endpoint is registered to /q/health providing a default health check. { "status": "UP", "checks": [ ] } To create a custom health check you need to implement the HealthCheck interface and annotate either with @Readiness (ready to process requests) or @Liveness (is running) annotations. @Readiness public class DatabaseHealthCheck implements HealthCheck { @Override public HealthCheckResponse call() { HealthCheckResponseBuilder responseBuilder = HealthCheckResponse.named("Database conn"); try { checkDatabaseConnection(); responseBuilder.withData("connection", true); responseBuilder.up(); } catch (IOException e) { // cannot access the database responseBuilder.down() .withData("error", e.getMessage()); } return responseBuilder.build(); } } Builds the next output: { "status": "UP", "checks": [ { "name": "Database conn", "status": "UP", "data": { "connection": true } } ] } Since health checks are CDI beans, you can do: @ApplicationScoped public class DatabaseHealthCheck { @Liveness HealthCheck check1() { return io.smallrye.health.HealthStatus .up("successful-live"); } @Readiness HealthCheck check2() { return HealthStatus .state("successful-read", this::isReady) } private boolean isReady() {} } You can ping liveness or readiness health checks individually by querying /q/health/live or /q/health/ready.
  • 48. Quarkus comes with some HealthCheck implementations for checking service status. SocketHealthCheck: checks if host is reachable using a socket. UrlHealthCheck: checks if host is reachable using a Http URL connection. InetAddressHealthCheck: checks if host is reachable using InetAddress.isReachable method. @Liveness HealthCheck check1() { return new UrlHealthCheck("https://www.google.com") .name("Google-Check"); } If you want to override or set manually readiness/liveness probes, you can do it by setting health properties: quarkus.smallrye-health.root-path=/hello quarkus.smallrye-health.liveness-path=/customlive quarkus.smallrye-health.readiness-path=/customready Automatic readiness probes Some default readiness probes are provided by default if any of the next features are added: datasource A probe to check database connection status. kafka A probe to check kafka connection status. In this case you need to enable manually by setting quarkus.kafka.health.enabled to true. mongoDB A probe to check MongoDB connection status. neo4j A probe to check Neo4J connection status. artemis A probe to check Artemis JMS connection status. kafka-streams Liveness (for stream state) and Readiness (topics created) probes. vault A probe to check Vault conection status. gRPC A readiness probe for the gRPC services. Cassandra A readiness probe to check Cassandra connection status. Redis A readiness probe to check Redis connection status. You can disable the automatic generation by setting <component>.health.enabled to false. quarkus.datasource.myotherdatasource.health-exclude=true quarkus.datasource.health.enabled=true quarkus.kafka-streams.health.enabled=false quarkus.mongodb.health.enabled=false quarkus.neo4j.health.enabled=false In the case of Vault you can pass parameters to modify the call of the status endpoint in Vault. quarkus.vault.health.enabled=true quarkus.vault.health.stand-by-ok=true quarkus.vault.health.performance-stand-by-ok=true Health groups are supported to provide custom health checks groups: @io.smallrye.health.HealthGroup("mygroup1") public class SimpleHealthGroupCheck implements HealthCheck { } You can ping grouped health checks by querying /group/mygroup1. Group root path can be con gured: quarkus.smallrye-health.group-path=/customgroup MicroPro le Health currently doesn’t support returning reactive types, but SmallRye Health does. Implement the io.smallrye.health.api.AsyncHealthCheck interface instead of the org.eclipse.microprofile.health.HealthCheck. @Liveness @ApplicationScoped public class LivenessAsync implements AsyncHealthCheck { @Override public Uni<HealthCheckResponse> call() { return Uni.createFrom().item(HealthCheckResponse.up ("liveness-reactive")) .onItem().delayIt().by(Duration.ofMillis(10 )); } } Metrics Quarkus can utilize the MicroPro le Metrics spec to provide metrics support. ./mvnw quarkus:add-extension -Dextensions="io.quarkus:quarkus-smallrye-metrics" The metrics can be read with JSON or the OpenMetrics format. An endpoint is registered automatically at /q/metrics providing default metrics. MicroPro le Metrics annotations: @Timed Tracks the duration. @SimplyTimed Tracks the duration without mean and distribution calculations. @Metered Tracks the frequency of invocations. @Counted Counts number of invocations. @Gauge Samples the value of the annotated object. @ConcurrentGauge Gauge to count parallel invocations. @Metric Used to inject a metric. Valid types Meter, Timer, Counter, Histogram. Gauge only on producer methods/ elds. @GET //... @Timed(name = "checksTimer", description = "A measure of how long it takes to perform a hello.", unit = MetricUnits.MILLISECONDS) public String hello() {} @Counted(name = "countWelcome", description = "How many welcome have been performed.") public String hello() {} @Gauge annotation returning a measure as a gauge. @Gauge(name = "hottestSauce", unit = MetricUnits.NONE, description = "Hottest Sauce so far.") public Long hottestSauce() {} Injecting a histogram using @Metric.
  • 49. @Inject @Metric(name = "histogram") Histogram historgram; You can con gure Metrics: quarkus.smallrye-metrics.path=/mymetrics Pre x is quarkus.smallrye-metrics. path The path to the metrics handler. (default: /q/metrics) extensions.enabled Metrics are enabled or not. (default: true) micrometer.compatibility Apply Micrometer compatibility mode. (default: false) quarkus.hibernate-orm.metrics.enabled set to true exposes Hibernate metrics under vendor scope. quarkus.mongodb.metrics.enabled set to true exposes MongoDB metrics under vendor scope. You can apply metrics annotations via CDI stereotypes: @Stereotype @Retention(RetentionPolicy.RUNTIME) @Target({ ElementType.TYPE, ElementType.METHOD, ElementTyp e.FIELD }) @Timed(name = "checksTimer", description = "A measure of how long it takes to perform a hello.", unit = MetricUnits.MILLISECONDS) public @interface TimedMilliseconds { } There is a tight integration with Micrometer in the form of an extension: ./mvnw quarkus:add-extension -Dextensions="micrometer" Add a micrometer dependency for the registry of your choosing: <dependency> <groupId>io.micrometer</groupId> <artifactId>micrometer-registry-prometheus</artifactId> </dependency> You can con gure Micrometer. Pre x is quarkus.micrometer: enabled Micrometer metrics support. (default: true) registry-enabled-default Micrometer MeterRegistry discovery. (default: true) binder-enabled-default Micrometer MeterBinder discovery. (default: true) binder.vertx.enabled Vert.x metrics support. binder.mp-metrics.enabled Micropro le Metrics support. binder.jvm Micrometer JVM metrics support. (default: true) binder.system Micrometer System metrics support. (default: true) export.datadog.enabled Support for export to Datadog Support for Datadog. export.jmx.enabled Support for export to JMX Support for JMX. export.prometheus.enabled Support for export to Prometheus. export.prometheus.path The path for the prometheus metrics endpoint (produces text/plain). (default: /q/metrics) export.azuremonitor.enabled Support for export to Azure Monitor. export.azuremonitor.instrumentation-key The path for the azure monitor instrumentationKey. export.statsd.enabled Support for export to StatsD. export.stackdriver.enabled Micrometer metrics support. (default: true) export.signalfx.enabled Micrometer metrics support. (default: true) export.signalfx.uri Signalfx URI. export.signalfx.access-token Access Token. binder.vertx.match-patterns Comma-separated case-sensitive list of regular expressions de ning Paths that should be matched and used as tags binder.vertx.ignore-patterns Comma-separated case-sensitive list of regular expressions de ning Paths that should be ignored / not measured. export.datadog Datadog MeterRegistry con guration in Map<String, String> format. export.jmx JMX registry con guration properties in Map<String, String> format. export.prometheus Prometheus registry con guration properties in Map<String, String> format. export.stackdriver Stackdriver registry con guration properties in Map<String, String> format. Tracing Quarkus can utilize the MicroPro le OpenTracing spec. ./mvnw quarkus:add-extension -Dextensions="io.quarkus:quarkus-smallrye-opentracing" Requests sent to any endpoint are traced automatically. This extension includes OpenTracing support and Jaeger tracer. Jaeger tracer con guration: quarkus.jaeger.service-name=myservice quarkus.jaeger.sampler-type=const quarkus.jaeger.sampler-param=1 quarkus.jaeger.endpoint=http://localhost:14268/api/traces quarkus.jaeger.metrics.enabled=true @Traced annotation can be set to disable tracing at class or method level. Tracer class can be injected into the class. @Inject Tracer tracer; tracer.activeSpan().setBaggageItem("key", "value"); You can disable Jaeger extension by using quarkus.jaeger.enabled property. You can log the traceId, spanId and sampled in normal log:
  • 50. quarkus.log.console.format=%d{HH:mm:ss} %-5p traceId=%X{tra ceId}, spanId=%X{spanId}, sampled =%X{sampled} [%c{2.}] (%t) %s%e%n Additional tracers JDBC Tracer Adds a span for each JDBC queries. <dependency> <groupId>io.opentracing.contrib</groupId> <artifactId>opentracing-jdbc</artifactId> </dependency> Con gure JDBC driver apart from tracing properties seen before: # add ':tracing' to your database URL quarkus.datasource.url= jdbc:tracing:postgresql://localhost:5432/mydatabase quarkus.datasource.driver= io.opentracing.contrib.jdbc.TracingDriver quarkus.hibernate-orm.dialect= org.hibernate.dialect.PostgreSQLDialect OpenTelemetry ./mvnw quarkus:add-extension -Dextensions="opentelemetry-otlp-exporter" Possible con guration: quarkus.application.name=myservice quarkus.opentelemetry.enabled=true quarkus.opentelemetry.tracer.exporter.otlp.endpoint=http:// localhost:4317 quarkus.opentelemetry.tracer.exporter.otlp.headers=Authoriz ation=Bearer my_secret The OpenTelemetry extension enables the W3C Trace Context and the W3C Baggage propagators, you can however choose any of the supported OpenTelemetry propagators. The b3, b3multi, jaeger and ottrace propagators: <dependency> <groupId>io.opentelemetry</groupId> <artifactId>opentelemetry-extension-trace-propagators</ artifactId> </dependency> The propagator: <dependency> <groupId>io.opentelemetry</groupId> <artifactId>opentelemetry-extension-aws</artifactId> </dependency> You can con gure OpenTelemetry. Pre x is quarkus.opentelemetry: enabled OpenTelemetry support (default: true) propagators Comma separated list of OpenTelemetry propagators which must be supported. Possible values b3, b3multi, baggage, jaeger, ottrace, tracecontext, xray (default: traceContext,baggage). tracer.enabled Support for tracing with OpenTelemetry. tracer.resource-attributes A comma separated list of name=value resource attributes that represents the entity producing telemetry tracer.sampler The sampler to use for tracing. Possible values off, on, ratio. (Default: on) tracer.sampler.ratio Ratio to sample tracer.sampler.parent-based If the sampler to use for tracing is parent based (default: true) tracer.suppress-non-application-uris Suppress non-application uris from trace collection. (default: true) tracer.exporter.otlp.enabled OTLP SpanExporter support (default: true) tracer.exporter.otlp.endpoint The OTLP endpoint to connect to tracer.exporter.otlp.headers Key-value pairs to be used as headers associated with gRPC requests tracer.exporter.otlp.export-timeout The maximum amount of time to wait for the collector to process exported spans before an exception is thrown. (default: 10S) tracer.exporter.otlp.compression Compression method to be used by exporter to compress the payload Kafka Tracer Adds a span for each message sent to or received from a Kafka t i <dependency> <groupId>io.opentracing.contrib</groupId> <artifactId>opentracing-kafka-client<</artifactId> </dependency> And con gure it: ... mp.messaging.outgoing.generated-price.topic=prices # For Produces mp.messaging.outgoing.generated-price.interceptor.classes=i o.opentracing.contrib.kafka.TracingProducerInterceptor ... # For consumers mp.messaging.incoming.prices.interceptor.classes=io.opentra cing.contrib.kafka.TracingConsumerInterceptor AWS XRay If you are building native images, and want to use AWS X-Ray Tracing with your lambda you will need to include quarkus-amazon- lambda-xray as a dependency in your pom.
  • 51. Native Executable You can build a native image by using GraalVM. The common use case is creating a Docker image so you can execute the next commands: ./mvnw package -Pnative -Dquarkus.native.container-build=tr ue docker build -f src/main/docker/Dockerfile.native -t quarkus/getting-started . docker run -i --rm -p 8080:8080 quarkus/getting-started You can use quarkus.native.container-runtime to select the container runtime to use. Now docker (default) and podman are the valid options. ./mvnw package -Pnative -Dquarkus.native.container-runtime= podman To con gure native application, you can create a config directory at the same place as the native le and place an application.properties le inside. config/application.properties. To produce a native executable with native excutable use - Dquarkus.native.additional-build-args=-J—enable-preview. SSL To create a native image with SSL you need to copy SunEC library and certi cates: Java 8: FROM quay.io/quarkus/ubi-quarkus-native-image:{graalvm-vers ion}-java8 as nativebuilder RUN mkdir -p /tmp/ssl-libs/lib && cp /opt/graalvm/jre/lib/security/cacerts /tmp/ssl-libs && cp /opt/graalvm/jre/lib/amd64/libsunec.so /tmp/ssl-lib s/lib/ FROM registry.access.redhat.com/ubi8/ubi-minimal WORKDIR /work/ COPY --from=nativebuilder /tmp/ssl-libs/ /work/ COPY target/*-runner /work/application RUN chmod 775 /work /work/application EXPOSE 8080 CMD ["./application", "-Dquarkus.http.host=0.0.0.0", "-Djav a.library.path=/work/lib", "-Djavax.net.ssl.trustStore=/wor k/cacerts"] Java 11: FROM quay.io/quarkus/ubi-quarkus-native-image:{graalvm-vers ion}-java11 as nativebuilder RUN mkdir -p /tmp/ssl-libs/lib && cp /opt/graalvm/lib/security/cacerts /tmp/ssl-libs && cp /opt/graalvm/lib/libsunec.so /tmp/ssl-libs/lib/ FROM registry.access.redhat.com/ubi8/ubi-minimal WORKDIR /work/ COPY --from=nativebuilder /tmp/ssl-libs/ /work/ COPY target/*-runner /work/application RUN chmod 775 /work /work/application EXPOSE 8080 CMD ["./application", "-Dquarkus.http.host=0.0.0.0", "-Djav a.library.path=/work/lib", "-Djavax.net.ssl.trustStore=/wor k/cacerts"] Inclusion of resources By default, no resources are included in native executable. quarkus.native.resources.includes allows to set glob expressions to include resources based on src/main/resources path. Given src/main/resources/foo/selected.png: quarkus.native.resources.includes=foo/** Exclusion of resources By default, no resources are excluded. quarkus.native.resources.excludes = foo/** Native con guration properties pre xed with quarkus.native: additional-build-args Additional arguments to pass to the build process. enable-http-url-handler If the HTTP url handler should be enabled. (default: true) enable-https-url-handler If the HTTPS url handler should be enabled. enable-all-security-services If all security services should be added to the native image. user-language De nes the user language used for building the native executable. user-country De nes the user country used for building the native executable. file-encoding De nes the le encoding. If all character sets should be added to the native image. graalvm-home The location of the Graal distribution. java-home The location of the JDK. native-image-xmx The maximum Java heap to be used during the native image generation. debug-build-process If the native image build should wait for a debugger to be attached before running. publish-debug-build-process-port If the debug port should be published when building with docker and debug-build-process. (default: true) cleanup-server If the native image server should be restarted. enable-isolates If isolates should be enabled. (default: true) enable-fallback-images If a JVM based 'fallback image' should be created if native image fails. enable-server If the native image server should be used. auto-service-loader-registration If all META-INF/services entries should be automatically registered. dump-proxies If the bytecode of all proxies should be dumped for inspection. container-build If this build should be done using a container runtime. remote-container-build If this build is done using a remote docker daemon. builder-image The docker image to use to do the image build. container-runtime The container runtime that is used to do an image based build. (docker, podman) container-runtime-options Options to pass to the container runtime. enable-vm-inspection If the resulting image should allow VM introspection
  • 52. full-stack-traces If full stack traces are enabled in the resulting image. enable-reports If the reports on call paths and included packages/classes/methods should be generated. report-exception-stack-traces If exceptions should be reported with a full stack trace. report-errors-at-runtime If errors should be reported at runtime. enable-dashboard-dump Generate the report les for GraalVM Dashboard. resources.includes A comma separated list of globs to match resource paths that should be added to the native image. resources.excludes A comma separated list of globs to match resource paths that should exclude to the native image. debug.enabled If debug is enabled and debug symbols are generated. Container Images Creation You can levarage to Quarkus to generation and release of Docker containers. It provides several extensions to make it so. mvn clean package -Dquarkus.container-image.build=true -Dquarkus.container-image.push=true -Dquarkus.container-image.registry=quay.io Pre x is quarkus.container-image: group The group/repository of the image. (default: the ${user.name}) name The name of the image. (default: the application name) tag The tag of the image. (default: the application version) additional-tags Additional tags of the container image. registry The registry to use for pushing. (default: docker.io) username The registry username. password The registry password. insecure Flag to allow insecure registries. (default: false) build Boolean to set if image should be built. (default: false) push Boolean to set if image should be pushed. (default: false) labels Custom labels to add to the generated image. Jib ./mvnw quarkus:add-extensions -Dextensions="quarkus-container-image-jib" Quarkus copies any le under src/main/jib into the built container image. Pre x is quarkus.container-image-jib: base-jvm-image The base image to use for the jib build. (default: fabric8/java- alpine-openjdk8-jre) base-native-image The base image to use for the native build. (default: registry.access.redhat.com/ubi8/ubi-minimal) jvm-arguments The arguments to pass to java. (default: - Dquarkus.http.host=0.0.0.0,- Djava.util.logging.manager=org.jboss.logmanager.LogManager) native-arguments The arguments to pass to the native application. (default: - Dquarkus.http.host=0.0.0.0) environment-variables Map of environment variables. jvm-entrypoint A custom entry point of the container image in JVM mode. native-entrypoint A custom entry point of the container image in native mode. offline-mode Whether or not to operate o ine. (default: false) base-registry-username The username to use to authenticate with the registry used to pull the base JVM image. base-registry-password The password to use to authenticate with the registry used to pull the base JVM image. ports The ports to expose. user The user to use in generated image. always-cache-base-image Controls the optimization which skips downloading base image layers that exist in a target registry (default: false). appcds-builder-image When AppCDS generation is enabled, if this property is set, then the JVM used to generate the AppCDS le will be the JVM present in the container image. platforms List of target platforms. (ie linux/amd64). docker-executable-ame Name of binary used to execute the docker commands. Docker ./mvnw quarkus:add-extensions -Dextensions="quarkus-container-image-docker" Pre x is quarkus.container-image-s2i: dockerfile-jvm-path Path to the JVM Docker le. (default: ${project.root}/src/main/docker/Dockerfile.jvm) dockerfile-native-path Path to the native Docker le. (default: ${project.root}/src/main/docker/Dockerfile.native) Buildpacks ./mvnw quarkus:add-extensions -Dextensions="quarkus-container-image-buildpack" Pre x is quarkus.buildpack: jvm-builder-image The buildpacks builder image to use when building the project in jvm mode. native-builder-image The buildpacks builder image to use when building the project in native mode. builder-env
  • 53. Environment key/values to pass to buildpacks. run-image The buildpacks run image to use when building the project. pull-timeout-seconds Max pull timeout for builder/run images, in seconds (default: 300) docker-host DOCKER_HOST value to use. log-level Log level to use. (default info) base-registry-username The username to use to authenticate with the registry used to pull the base image. base-registry-password The password to use to authenticate with the registry used to pull the base image. S2I ./mvnw quarkus:add-extensions -Dextensions="quarkus-container-image-s2i" Pre x is quarkus.container-image-docker: base-jvm-image The base image to use for the s2i build. (default: fabric8/java- alpine-openjdk8-jre) base-native-image The base image to use for the native build. (default: registry.access.redhat.com/ubi8/ubi-minimal) Kubernetes Quarkus can use Dekorate to generate Kubernetes resources. ./mvnw quarkus:add-extensions -Dextensions="quarkus-kubernetes" Running ./mvnw package the Kubernetes resources are created at target/kubernetes/ directory. Container Images Creation integrates with Kubernetes extension, so no need of extra Kubernetes properties. Generated resource is integrated with MicroPro le Health annotations. Also, you can customize the generated resource by setting the new values in application.properties: quarkus.kubernetes.namespace=mynamespace quarkus.kubernetes.replicas=3 quarkus.kubernetes.labels.foo=bar quarkus.kubernetes.readiness-probe.period-seconds=45 quarkus.kubernetes.mounts.github-token.path=/deployment/git hub quarkus.kubernetes.mounts.github-token.read-only=true quarkus.kubernetes.secret-volumes.github-token.volume-name= github-token quarkus.kubernetes.secret-volumes.github-token.secret-name= greeting-security quarkus.kubernetes.secret-volumes.github-token.default-mode =420 quarkus.kubernetes.config-map-volumes.github-token.config-m ap-name=my-secret quarkus.kubernetes.expose=true quarkus.kubernetes.ingress.expose=true quarkus.kubernetes.ingress.host=example.com quarkus.kubernetes.env.vars.my-env-var=foobar quarkus.kubernetes.env.configmaps=my-config-map,another-con fig-map quarkus.kubernetes.env.secrets=my-secret,my-other-secret quarkus.kubernetes.resources.requests.memory=64Mi quarkus.kubernetes.resources.requests.cpu=250m quarkus.kubernetes.resources.limits.memory=512Mi quarkus.kubernetes.resources.limits.cpu=1000m All possible values are explained at https://quarkus.io/guides/kubernetes#con guration-options. Labels and Annotations The generated manifest use the Kubernetes recommended labels and annotations. "labels" : { "app.kubernetes.io/part-of" : "todo-app", "app.kubernetes.io/name" : "todo-rest", "app.kubernetes.io/version" : "1.0-rc.1" } "annotations": { "app.quarkus.io/vcs-url" : "<some url>", "app.quarkus.io/commit-id" : "<some git SHA>", } You can override the labels by using the next properties: quarkus.kubernetes.part-of=todo-app quarkus.kubernetes.name=todo-rest quarkus.kubernetes.version=1.0-rc.1 Or add new labels and/or annotations: quarkus.kubernetes.labels.foo=bar quarkus.kubernetes.annotations.foo=bar metrics When using metrics extension, Prometheus annotations are generated: prometheus.io/scrape: "true" prometheus.io/path: /metrics prometheus.io/port: "8080" Kubernetes Deployment Targets You can generate different resources setting the property quarkus.kubernetes.deployment-target. Possible values are kubernetes, openshift and knative. The default value is kubernetes. Knative Properties Most of the Kubernetes properties are valid in Knative output by just changing the kubernetes pre x to knative pre x (ie quarkus.kubernetes.readiness-probe.period-seconds to quarkus.knative.readiness-probe.period-seconds). There are also speci c properties for Knative: quarkus.kubernetes.deployment-target=knative quarkus.knative.revision-name=my-revision quarkus.knative.traffic.my-revision.percentage=80 List of con guration options: kubernetes https://quarkus.io/guides/kubernetes#con guration-options openshift https://quarkus.io/guides/kubernetes#openshift Knative https://quarkus.io/guides/kubernetes#knative Using Existing Resources You an provide your Kubernetes resources in form of yaml/json and they will provide additional resources or be used as base for the generation process:
  • 54. Resources are added in src/main/kubernetes directory with the target name (kubernetes.json, openshift.json, knative.json, or the yml equivalents) with one orm ore Kubernetes resources. Any resource found will be added in the generated manifests. If one of the provided resources has the same name as one of the generated ones, then the generated resource will be created on top of the provided resource, respecting existing content. To override the name of the generated resource you can use: quarkus.kubernetes.name, quarkus.openshift.name and quarkus.knative.name. Deployment To deploy automatically the generated resources, you need to set quarkus.container.deploy ag to true. mvn clean package -Dquarkus.kubernetes.deploy=true If you set this ag to true, the build and push ags from container-image are set to true too. To deploy the application, the extension uses the https://github.com/fabric8io/kubernetes-client. All options described at Kubernetes Client are valid here. Kubernetes Service Binding Quarkus supports binding services to applications via the Service Binding Speci cation for Kubernetes. The following Quarkus extensions support this feature: quarkus-jdbc-mariadb quarkus-jdbc-mssql quarkus-jdbc-mysql quarkus-jdbc-postgresql quarkus-kafka-client quarkus-smallrye-reactive-messaging-kafka quarkus-mongodb ./mvnw quarkus:add-extensions -Dextensions="quarkus-kubernetes-service-binding" Datasource con guration part is absent as it is auto-discovered by Quarkus. Minikube Quarkus has a Minikube extension which creates Kubernetes manifests that are tailored for Minikube. ./mvnw quarkus:add-extension -Dextensions="minikube" Remember to execute eval $(minikube -p minikube docker- env) to build images directly inside Minkube cluster. OpenShift Instead of adding Kubernetes extension, set container image s2i and the target to openshift for working with OpenShift, an extension grouping all of the is created: ./mvnw quarkus:add-extension -Dextensions="openshift" Kubernetes Con guration Extension Integration between MicroPro le Con g spec and Con gMaps & Secrets: ./mvnw quarkus:add-extensions -Dextensions="quarkus-kubernetes-config" quarkus.kubernetes-config.enabled=true quarkus.kubernetes-config.config-maps=cmap1,cmap2 @ConfigProperty(name = "some.prop1") String someProp1; @ConfigProperty(name = "some.prop2") String someProp2; If the con g key is a Quarkus con guration le application.properties/application.yaml, the content is parsed and each key of the con guration le is used as con g property. List of Kubernetes Con g parameters. quarkus.kubernetes-config as pre x is skipped in the next table. enabled The application will attempt to look up the con guration from the API server. (default: false) fail-on-missing-config The application will not start if any of the con gured con g sources cannot be located. (default: true) config-maps Con gMaps to look for in the namespace that the Kubernetes Client has been con gured for. Supports CSV. namespace Access to Con gMaps from a speci c namespace. secrets.enabled Whether or not con guration can be read from secrets. (default: false) Kubernetes Client Quarkus integrates with Fabric8 Kubernetes Client. ./mvnw quarkus:add-extension -Dextensions="quarkus-kubernetes-client" List of Kubernetes client parameters. quarkus.kubernetes-client as pre x is skipped in the next table. trust-certs Trust self-signed certi cates. (default: false) master-url URL of Kubernetes API server. namesapce Default namespace. ca-cert-file CA certi cate data. client-cert-file Client certi cate le. client-cert-data Client certi cate data. client-key-data Client key data. client-key-algorithm Client key algorithm. client-key-passphrase Client key passphrase. username Username. password Password. watch-reconnect-interval Watch reconnect interval. (default: PT1S) watch-reconnect-limit Maximum reconnect attempts. (default: -1) connection-timeout Maximum amount of time to wait for a connection. (default: PT10S)
  • 55. request-timeout Maximum amount of time to wait for a request. (default: PT10S) rolling-timeout Maximum amount of time to wait for a rollout. (default: PT15M) http-proxy HTTP proxy used to access the Kubernetes. https-proxy HTTPS proxy used to access the Kubernetes. proxy-username Proxy username. proxy-password Proxy password. no-proxy IP addresses or hosts to exclude from proxying Or programmatically: @Dependent public class KubernetesClientProducer { @Produces public KubernetesClient kubernetesClient() { Config config = new ConfigBuilder() .withMasterUrl("https://mymaster.com") .build(); return new DefaultKubernetesClient(config); } } And inject it on code: @Inject KubernetesClient client; ServiceList myServices = client.services().list(); Service myservice = client.services() .inNamespace("default") .withName("myservice") .get(); CustomResourceDefinitionList crds = client .customResourceDefinitions() .list(); dummyCRD = new CustomResourceDefinitionBuilder() ... .build() client.customResourceDefinitions() .create(dummyCRD); Testing Quarkus provides a Kubernetes Mock test resource that starts a mock of Kubernetes API server and sets the proper environment variables needed by Kubernetes Client. Register next dependency: io.quarkus:quarkus-test-kubernetes- client:test. @QuarkusTestResource(KubernetesMockServerTestResource.clas s) @QuarkusTest public class KubernetesClientTest { @MockServer private KubernetesMockServer mockServer; @Test public void test() { final Pod pod1 = ... mockServer .expect() .get() .withPath("/api/v1/namespaces/test/pods") .andReturn(200, new PodListBuilder() .withNewMetadata() .withResourceVersion("1") .endMetadata() .withItems(pod1, pod2) .build()) .always(); } } AWS Lambda Quarkus integrates with Amazon Lambda. ./mvnw quarkus:add-extension -Dextensions="io.quarkus:quarkus-amazon-lambda" And then implement com.amazonaws.services.lambda.runtime.RequestHandler interface. public class TestLambda implements RequestHandler<MyInput, MyOutput> { @Override public MyInput handleRequest(MyOutput input, Context context) { } } The interface com.amazonaws.services.lambda.runtime.RequestStreamHandler is also supported. The interface com.amazon.ask.SkillStreamHandler is also supported. You can set the handler name by using quarkus.lambda.handler b h bd h h annotation. Test You can write tests for Amazon lambdas: <dependency> <groupId>io.quarkus</groupId> <artifactId>quarkus-test-amazon-lambda</artifactId> <scope>test</scope> </dependency> @Test public void testLambda() { MyInput in = new MyInput(); in.setGreeting("Hello"); in.setName("Stu"); MyOutput out = LambdaClient.invoke(MyOutput.class, in); } To scaffold a AWS Lambda run: mvn archetype:generate -DarchetypeGroupId=io.quarkus -DarchetypeArtifactId=quarkus-amazon-lambda-archetype -DarchetypeVersion={version} Azure Functions Quarkus can make a microservice be deployable to the Azure Functions. To scaffold a deployable microservice to the Azure Functions run: mvn archetype:generate -DarchetypeGroupId=io.quarkus -DarchetypeArtifactId=quarkus-azure-functions-http-archet ype -DarchetypeVersion={version} Funqy Quarkus Funqy is part of Quarkus’s serverless strategy and aims to provide a portable Java API to write functions deployable to various FaaS environments like AWS Lambda, Azure Functions, Knative, and Knative events.
  • 56. public class GreetingFunction { @Inject GreetingService service; @io.quarkus.funqy.Funq public String greet(String name) {} @io.quarkus.funqy.Funq("HelloCustomer") public String greet(Customer name) {} @Funq public Greeting greet(Friend friend, @io.quarkus.funqy.Context AwsContext ctx) {} } In case of Amazon Lambda, only one Funqy function can be exported per Amazon Lambda deployment. If there is only one method annotated with @Funq then no prob, if not, you need to set the function name with quarkus.funqy.export property. Funqy HTTP You can invoke on Funqy functions in a pure HTTP environment with simple adding the Funqy HTTP extension. <dependency> <groupId>io.quarkus</groupId> <artifactId>quarkus-funqy-http</artifactId> </dependency> Funqy Cloud Events Add the extension: <dependency> <groupId>io.quarkus</groupId> <artifactId>quarkus-funqy-knative-events</artifactId> </dependency> @Funq public String defaultChain(String input) {} The Cloud Event type that triggers the function is defaultChain. It generates a response that triggers a new Cloud Event whose type is defaultChain.output and the event source is defaultChain. It can be changed by using the next properties: quarkus.funqy.knative-events.mapping.defaultChain.trigger=c onfigChain.output quarkus.funqy.knative-events.mapping.defaultChain.response- type=annotated quarkus.funqy.knative-events.mapping.defaultChain.response- source=configChain The properties are of form: quarkus.funqy.knative-events.mapping. {function name}.. Also can be overriden with @io.quarkus.funqy.knative.events.CloudEventMapping annotation. @Funq @CloudEventMapping(trigger = "annotated", responseSource = "annotated", responseType = "lastChainLink") public String annotatedChain(String input) {} responseType chains annotatedChain response to lastChainLink function. @Funq public void lastChainLink(String input, @Context io.quarkus.funqy.knative.events.CloudE vent event) {} A K-Native Trigger looks like: apiVersion: eventing.knative.dev/v1alpha1 kind: Trigger metadata: name: defaultchain spec: filter: attributes: type: defaultChain subscriber: ref: apiVersion: serving.knative.dev/v1 kind: Service name: funqy-knative-events-quickstart And to curl from inside the Kubernetes cluster: curl -v "http://default-broker.knativetutorial.svc.cluster. local" -X POST -H "Ce-Id: 1234" -H "Ce-Specversion: 1.0" -H "Ce-Type: defaultChain" -H "Ce-Source: curl" -H "Content-Type: application/json" -d '"Start"' Apache Camel Apache Camel Quarkus has its own site: https://github.com/apache/camel-quarkus WebSockets Quarkus can be used to handling web sockets. ./mvnw quarkus:add-extension -Dextensions="quarkus-websockets" If you only want the client you can include quarkus-websockets- client. And web sockets classes can be used: @ServerEndpoint("/chat/{username}") @ApplicationScoped public class ChatSocket { @OnOpen public void onOpen(Session session, @PathParam("username") String username) {} @OnClose public void onClose(..) {} @OnError public void onError(..., Throwable throwable) {} @OnMessage public void onMessage(...) {} } OpenAPI Quarkus can expose its API description as OpenAPI spec and test it using Swagger UI. ./mvnw quarkus:add-extension -Dextensions="io.quarkus:quarkus-smallrye-openapi" Then you only need to access to /openapi to get OpenAPI v3 spec of services. You can update the OpenApi path by setting quarkus.smallrye- openapi.path property. Also, in case of starting Quarkus application in dev or test mode, Swagger UI is accessible at /swagger-ui. If you want to use it in production mode you need to set quarkus.swagger-ui.always- include property to true. You can update the Swagger UI path by setting quarkus.swagger- ui.path property.
  • 57. quarkus.swagger-ui.path=/my-custom-path Possible Swagger UI options with quarkus.swagger-ui pre x: urls The urls that will be included as options. (ie quarkus.swagger- ui.urls.petstore=https://petstore.swagger.io/v2/swagger.json) urls-primary-name If urls option is used, this will be the name of the default selection. title The html title for the page. theme Swagger UI theme to be used. footer A footer for the html page. Nothing by default. deep-linking Enables deep linking for tags and operations. display-operation-id Controls the display of operationId in operations list. default-models-expand-depth The default expansion depth for models. default-model-expand-depth The default expansion depth for the model on the model-example section. default-model-rendering Controls how the model is shown when the API is rst rendered. display-request-duration Controls the display of the request duration (in milliseconds) for "Try it out" requests. doc-expansion Controls the default expansion setting for the operations and tags. filter Enables ltering. max-displayed-tags Limits the number of tagged operations displayed to at most this many. operations-sorter Apply a sort to the operation list of each API. (alpha, method, function) h t i Controls the display of vendor extension. show-common-extensions Controls the display of extensions. tag-sorter Apply a sort to the tag list of each API. on-complete Provides a mechanism to be noti ed when Swagger UI has nished rendering a newly provided de nition. syntax-highlight Set to false to deactivate syntax highlighting of payloads and cURL command. oauth2-redirect-url OAuth redirect URL. request-interceptor Function to intercept remote de nition, "Try it out", and OAuth 2.0 requests. request-curl-options Array of command line options available to the curl command. response-interceptor Function to intercept remote de nition, "Try it out", and OAuth 2.0 responses. show-mutated-request Uses the mutated request returned from a requestInterceptor to produce the curl command in the UI. supported-submit-methods List of HTTP methods that have the "Try it out" feature enabled. validator-url Swagger UI attempts to validate specs against swagger.io’s online validator. with-credentials Enables passing credentials, as de ned in the Fetch standard, in CORS requests that are sent by the browser. model-property-macro Function to set default values to each property in model. parameter-macro Function to set default value to parameters. persist-authorization It persists authorization data and it would not be lost on browser close/refresh. layout The name of a component available via the plugin system to use as the top-level layout for Swagger UI. plugins A list of plugin functions to use in Swagger UI. presets A list of presets to use in Swagger UI. You can customize the output by using Open API v3 annotations. @Schema(name="Developers", description="POJO that represents a developer.") public class Developer { @Schema(required = true, example = "Alex") private String name; } @POST @Path("/developer") @Operation(summary = "Create deeloper", description = "Only be done by admin.") public Response createDeveloper( @RequestBody(description = "Developer object", required = true, content = @Content(schema = @Schema(implementation = Developer.class))) Developer developer) All possible annotations can be seen at org.eclipse.micropro le.openapi.annotations package. You can also serve OpenAPI Schema from static les instead of dynamically generated from annotation scanning. You need to put OpenAPIdocumentation under META-INF directory (ie: META-INF/openapi.yaml). A request to /openapi will serve the combined OpenAPI document from the static le and the generated from annotations. You can disable the scanning documents by adding the next con guration property: mp.openapi.scan.disable=true. Other valid document paths are: META-INF/openapi.yml, META- INF/openapi.json, WEB-INF/classes/META-INF/openapi.yml, WEB- INF/classes/META-INF/openapi.yaml, WEB-INF/classes/META- INF/openapi.json. You can store generated OpenAPI schema if quarkus.swagger- ui.store-schema-directory is set. Possible OpenAPI options with quarkus.smallrye-openapi pre x: path The path at which to register the OpenAPI Servlet. (default: openapi) store-schema-directory The generated OpenAPI schema documents will be stored here on build. always-run-filter Do not run the lter only at startup, but every time the document is requested (dynamic). (default: false)
  • 58. ignore-static-document Do not include the provided static openapi document. (default: false) additional-docs-directory A list of local directories that should be scanned for yaml and/or json les to be included in the static model. security-scheme Add a certain SecurityScheme with con g. (basic, jwt, oidc, oauth2Implicit) security-scheme-name Add a Security Scheme name to the generated OpenAPI document. (default: SecurityScheme) security-scheme-description Add a description to the Security Scheme. (default: Authentication) basic-security-scheme-value Add a scheme value to the Basic HTTP Security Scheme. (default: basic) jwt-security-scheme-value Add a scheme value to the JWT Security Scheme. (default: bearer) jwt-bearer-format Add a bearer format to the JWT Security Scheme. (default: JWT) oidc-open-id-connect-url Add a openIdConnectUrl value to the OIDC Security Scheme oauth2-implicit-refresh-url Add a implicit ow refreshUrl value to the OAuth2 Security Scheme oauth2-implicit-authorization-url Add an implicit ow authorizationUrl value to the OAuth2 Security Scheme oauth2-implicit-token-url Add an implicit ow tokenUrl value to the OAuth2 Security Scheme open-api-version Override the openapi version in the Schema document info-title Set the title in Info tag in the Schema document info-version Set the version in Info tag in the Schema document info-description Set the description in Info tag in the Schema document info-terms-of-service Set the terms of the service in Info tag in the Schema document info-contact-email Set the contact email in Info tag in the Schema document info-contact-name Set the contact name in Info tag in the Schema document info-contact-url Set the contact url in Info tag in the Schema document info-license-name Set the license name in Info tag in the Schema document info-license-url Set the license url in Info tag in the Schema document operation-id-strategy Set the strategy to automatically create an operation Id. Possible values: method,class-method, package-class-method Mail Sender You can send emails by using Quarkus Mailer extension: ./mvnw quarkus:add-extension -Dextensions="io.quarkus:quarkus-mailer" You can inject two possible classes io.quarkus.mailer.Mailer for synchronous API or io.quarkus.mailer.reactive.ReactiveMailer for asynchronous/reactive API. @Inject Mailer mailer; And then you can use them to send an email: mailer.send( Mail.withText("to@acme.org", "Subject", "Body") ); Reactive Mail client @Inject ReactiveMailer reactiveMailer; CompletionStage<Response> stage = reactiveMailer.send( Mail.withText("to@acme.org", "Subject", "Body") ) .subscribeAsCompletionStage() .thenApply(x -> Response.accepted().build()); If you are using quarkus-resteasy-mutiny, you can return io.smallrye.mutiny.Uni type. Mail class contains methods to add cc, bcc, headers, bounce address, reply to, attachments, inline attachments and html body. mailer.send(Mail.withHtml("to@acme.org", "Subject", body) .addInlineAttachment("quarkus.png", new File("quarkus.png"), "image/png", "<my-image@quarkus.io>")); If you need deep control you can inject Vert.x mail client @Inject MailClient client; You need to con gure SMTP properties to be able to send an email: quarkus.mailer.from=test@quarkus.io quarkus.mailer.host=smtp.sendgrid.net quarkus.mailer.port=465 quarkus.mailer.ssl=true quarkus.mailer.username=.... quarkus.mailer.password=.... List of Mailer parameters. quarkus. as a pre x is skipped in the next table. Parameter Default Description mailer.from Default address. mailer.mock false in prod, true in dev and test. Emails not sent, just printed and stored in a MockMailbox. mailer.bounce- address Default address. mailer.host mandatory SMTP host. mailer.port 25 SMTP port. mailer.username The username. mailer.password The password. mailer.ssl false Enables SSL. mailer.trust-all false Trust all certi cates. mailer.max-pool-size 10 Max open connections .
  • 59. Parameter Default Description mailer.own-host-name Hostname for HELO/EHLO and Message-ID mailer.keep-alive true Connection pool enabled. mailer.disable-esmtp false Disable ESMTP. mailer.start-tls OPTIONAL TLS security mode. DISABLED, OPTIONAL, REQUIRED. mailer.login NONE Login mode. NONE, OPTIONAL, REQUIRED. mailer.auth-methods All methods. Space-separated list. mailer.key-store Path of the key store. mailer.key-store- password Key store password. if you enable SSL for the mailer and you want to build a native executable, you will need to enable the SSL support quarkus.ssl.native=true. Testing If quarkus.mailer.mock is set to true, which is the default value in dev and test mode, you can inject MockMailbox to get the sent messages. @Inject MockMailbox mailbox; @BeforeEach void init() { mailbox.clear(); } List<Mail> sent = mailbox .getMessagesSentTo("to@acme.org"); Scheduled Tasks You can schedule periodic tasks with Quarkus. @ApplicationScoped public class CounterBean { @Scheduled(every="10s", delayed="1s") void increment() {} @Scheduled(cron="0 15 10 * * ?") void morningTask() {} } every and cron parameters can be surrounded with {} and the value is used as con g property to get the value. @Scheduled(cron = "${morning.check.cron.expr}") void morningTask() {} @Scheduled(cron = "${myMethod.cron.expr:0 0 15 ? * MON *}") void myMethod() {} And con gure the property into application.properties: morning.check.cron.expr=0 15 10 * * ? morning.check.cron.expr=disabled By default Quarkus expresion is used, but you can change that by setting quarkus.scheduler.cron-type property. quarkus.scheduler.cron-type=unix org.quartz.Scheduler can be injected as any other bean and scehdule jobs programmatically. @Inject org.quartz.Scheduler quartz; quartz.scheduleJob(job, trigger); Quarkus provides a built-in bean of type io.quarkus.scheduler.Scheduler: @Inject io.quarkus.scheduler.Scheduler scheduler; scheduler.pause(); // Pause all scheduler.pause("myIdentity"); // Pause a specific schedule d method by its identity scheduler.resume("myIdentity"); scheduler.resume() Kogito Quarkus integrates with Kogito, a next-generation business automation toolkit from Drools and jBPM projects for adding business automation capabilities. To start using it you only need to add the next extension: ./mvnw quarkus:add-extension -Dextensions="kogito" DevServices When testing or running in dev mode Quarkus can even provide you with a zero con g Kogito out of the box. Possible con guration values pre xed with quarkus.kogito: devservices.enabled If devservices is enabled or not. (default: true) devservices.image-name The container image name to use instead of the default one. (default: quay.io/kiegroup/kogito-data-index-ephemeral) devservices.port Optional xed port the dev service will listen to. (default: 8180) devservices.shared Indicates if the Data Index instance managed by Quarkus Dev Services is shared. When shared, Quarkus looks for running containers using label-based service discovery. (default: true) devservices.service-name The value of the kogito-dev-service-data-index label attached to the started container. (default: kogito-data-index) Apache Tika Quarkus integrates with Apache Tika to detect and extract metadata/text from different le types: ./mvnw quarkus:add-extension -Dextensions="quarkus-tika" @Inject io.quarkus.tika.TikaParser parser; @POST @Path("/text") @Consumes({ "text/plain", "application/pdf", "application/vnd.oasis.opendocument.text" }) @Produces(MediaType.TEXT_PLAIN) public String extractText(InputStream stream) { return parser.parse(stream).getText(); } You can con gure Apache Tika in application.properties le by using next properties pre xed with k :
  • 60. Parameter Default Description tika.tika-config- path tika-config.xml Path to the Tika con guration resource. quarkus.tika.parsers CSV of the abbreviated or full parser class to be loaded by the extension. tika.append-embedded- content true The document may have other embedded documents. Set if autmatically append. JGit Quarkus integrates with JGit to integrate with Git repositories: ./mvnw quarkus:add-extension -Dextensions="quarkus-jgit" And then you can start using JGit: try (Git git = Git.cloneRepository() .setDirectory(tmpDir) .setURI(url) .call()) { return tmpDir.toString(); } When running in native mode, make sure to con gure SSL access correctly quarkus.ssl.native=true (Native and SSL). Web Resources You can serve web resources with Quarkus. You need to place web resources at src/main/resources/META-INF/resources and then they are accessible (ie http://localhost:8080/index.html) By default static resources as served under the root context. You can change this by using quarkus.http.root-path property. Transactional Memory Quarkus integrates with the Software Transactional Memory (STM) implementation provided by the Narayana project. ./mvnw quarkus:add-extension -Dextensions="narayana-stm" Transactional objects must be interfaces and annotated with org.jboss.stm.annotations.Transactional. @Transactional @NestedTopLevel public interface FlightService { int getNumberOfBookings(); void makeBooking(String details); } The pessimistic strategy is the default one, you can change to optimistic by using @Optimistic. Then you need to create the object inside org.jboss.stm.Container. Container<FlightService> container = new Container<>(); FlightServiceImpl instance = new FlightServiceImpl(); FlightService flightServiceProxy = container.create(instanc e); The implementation of the service sets the locking and what needs to be saved/restored: import org.jboss.stm.annotations.ReadLock; import org.jboss.stm.annotations.State; import org.jboss.stm.annotations.WriteLock; public class FlightServiceImpl implements FlightService { @State private int numberOfBookings; @ReadLock public int getNumberOfBookings() { return numberOfBookings; } @WriteLock public void makeBooking(String details) { numberOfBookings += 1; } } Any member is saved/restored automatically (@State is not mandatory). You can use @NotState to avoid behaviour. Transaction boundaries Declarative @NestedTopLevel: De nes that the container will create a new top-level transaction for each method invocation. @Nested: De nes that the container will create a new top-level or nested transaction for each method invocation. Programmatically AtomicAction aa = new AtomicAction(); aa.begin(); { try { flightService.makeBooking("BA123 ..."); taxiService.makeBooking("East Coast Taxis ..."); aa.commit(); } catch (Exception e) { aa.abort(); } } Quartz Quarkus integrates with Quartz to schedule periodic clustered tasks. ./mvnw quarkus:add-extension -Dextensions="quartz" @ApplicationScoped public class TaskBean { @Transactional @Scheduled(every = "10s") void schedule() { Task task = new Task(); task.persist(); } } To con gure in clustered mode vida DataSource: quarkus.datasource.url=jdbc:postgresql://localhost/quarkus_ test quarkus.datasource.driver=org.postgresql.Driver # ... quarkus.quartz.clustered=true quarkus.quartz.store-type=db You need to de ne the datasource used by clustered mode and also import the database tables following the Quartz schema. Quartz can be con gured usinf the following properties with quarkus.quartz pre x: clustered Enable cluster mode or not. store-type The type of store to use. Possible values: ram, db (default: ram)
  • 61. datasource The name of the datasource to use. table-prefix The pre x for quartz job store tables. (default: QRTZ_) trigger-listeners.<name>.class Class name for the trigger. trigger-listeners.<name>.property-name The properties passed to the class. job-listeners.<name>.class Class name for the job. job-listeners.<name>.property-name The properties passed to the class. plugins.<name>.class Class name for the plugin. plugins.<name>.property-name The properties passed to the class. instance-name The name of the Quartz instance. (default: QuarkusQuartzScheduler) thread-count The size of scheduler thread pool. (default: 25) thread-priority Thread priority of worker threads in the pool. (default: 5) force-start The scheduler will be started even if no scheduled business methods are found. start-mode Scheduler can be started in different modes: normal, forced or halted. (default: normal) Qute Qute is a templating engine designed speci cally to meet the Quarkus needs. Templates should be placed by default at src/main/resources/templates aand subdirectories. ./mvnw quarkus:add-extension -Dextensions="quarkus-resteasy-qute" Templates can be de ned in any format, in case of HTML: item.html {@org.acme.Item item} <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>{item.name}</title> </head> <body> <h1>{item.name ?: 'Unknown'}</h1> <h2>{str:reverse('Hello')}</h2> <div>Price: {item.price}</div> {#if item.price > 100} <div>Discounted Price: {item.discountedPrice}</div> {/if} </body> </html> First line is not mandatory but helps on doing property checks at compilation time. Including templates passing parameters: <html> <head> <meta charset="UTF-8"> <title>Simple Include</title> </head> <body> {#include foo limit=10 /} </body> </html> To render the template: public class Item { public String name; public BigDecimal price; } @Inject io.quarkus.qute.Template item; @GET @Path("{id}") @Produces(MediaType.TEXT_HTML) public TemplateInstance get(@PathParam("id") Integer id) { return item.data("item", service.findItem(id)); } @TemplateExtension static BigDecimal discountedPrice(Item item) { return item.price.multiply(new BigDecimal("0.9")); } @TemplateExtension(namespace = "str") public static class StringExtensions { static String reverse(String val) { return new StringBuilder(val).reverse().toString(); } } If @ResourcePath is not used in Template then the name of the eld is used as le name. In this case the le should be src/main/resources/templates/item.{}. Extension of the le is not required to be set. discountedPrice is not a eld of the POJO but a method call. Method de nition must be annotated with @TemplateExtension and be static method. First parameter is used to match the base object (Item). @TemplateExtension can be used at class level: @TemplateExtension public class MyExtensions { static BigDecimal discountedPrice(Item item) { return item.price.multiply(new BigDecimal("0.9")); } } Methods with multiple parameters are supported too: {item.discountedPrice(2)} static BigDecimal discountedPrice(Item item, int scale) { return item.price.multiply(scale); } Qute for syntax supports any instance of Iterable, Map.EntrySet, Stream or Integer.
  • 62. {#for i in total} {i}: {/for} The next map methods are supported: {#for key in map.keySet} {#for value in map.values} {map.size} {#if map.isEmpty} {map['foo'] The next list methods are supported: {list[0]} The next number methods are supported: {#if counter.mod(5) == 0} Switch/When {#switch person.name} {#case 'John'} Hey John! {#case 'Mary'} Hey Mary! {/switch} {#when items.size} {#is 1} (1) There is exactly one item! {#is > 10} (2) There are more than 10 items! {#else} (3) There are 2 -10 items! {/when} Following operators can be used either in when and switch: not, ne, !=, gt, >, ge, >=, lt, <, le, <=, in, ni, !in. eval {#eval myData.template name='Mia' /} The result of myData.template will be used as the template. Message Bundling @io.quarkus.qute.i18n.MessageBundle public interface AppMessages { @io.quarkus.qute.i18n.Message("Hello {name}!") String hello_name(String name); } There are 3 methods to inject the message: MessageBundles.get(AppMessages.class).hello_name("Lucie"); or @Inject AppMessages app; app.hello_name("Lucie"); or <p>{msg:hello_name('Lucie')}</p> Localization There are two ways to set localized message: @io.quarkus.qute.i18n.Localized("de") public interface GermanAppMessages { @Override @io.quarkus.qute.i18n.Message("Hallo {name}!") String hello_name(String name); } or msg_de.properties hello_name=Hallo {name}! You can render programmaticaly the templates too: // file located at src/main/resources/templates/reports/v1/ report_01.{} @ResourcePath("reports/v1/report_01") Template report; String output = report .data("samples", service.get()) .render(); Value Resolvers Value resolvers are invoked when evaluating expressions. void configureEngine(@Observes EngineBuilder builder) { builder.addValueResolver(ValueResolver.builder() .appliesTo(ctx -> ctx.getBase() instanceof Long && ct x.getName().equals("tenTimes")) .resolveSync(ctx -> (Long) ctx.getBase() * 10) .build()); } Content Filters Content lters can be used to modify the template contents before parsing. void configureEngine(@Observes EngineBuilder builder) { builder.addParserHook(new ParserHook() { @Override public void beforeParsing(ParserHelper parserHelper) { parserHelper.addContentFilter(contents -> content s.replace("${", "${")); } }); } Reactive and Async CompletionStage<String> async = report.renderAsync(); Multi<String> publisher = report.createMulti(); Uni<String> content = io.smallrye.mutiny.Uni.createFrom() .completionStage(() -> report.r enderAsync()); Qute Mail Integration @Inject MailTemplate hello; CompletionStage<Void> c = hello.to("to@acme.org") .subject("Hello from Qute template") .data("name", "John") .send(); INFO: Template located at src/main/resources/templates/hello. [html|txt]. Sentry Quarkus integrates with Sentry for logging errors into an error monitoring system. ./mvnw quarkus:add-extension -Dextensions="quarkus-logging-sentry"
  • 63. And the con guration to send all errors occuring in the package org.example to Sentrty with DSN https://abcd@sentry.io/1234: quarkus.log.sentry=true quarkus.log.sentry.dsn=https://abcd@sentry.io/1234 quarkus.log.sentry.level=ERROR quarkus.log.sentry.in-app-packages=org.example Full list of con guration properties having quarkus.log as pre x: sentry.enable Enable the Sentry logging extension (default: false) sentry.dsn Where to send events. sentry.level Log level (default: WARN) sentry.server-name Sets the server name that will be sent with each event. sentry.in-app-packages Con gure which package pre xes your application uses. JSch Quarkus integrates with Jsch for SSH communication. ./mvnw quarkus:add-extension -Dextensions="quarkus-jsch" JSch jsch = new JSch(); Session session = jsch.getSession(null, host, port); session.setConfig("StrictHostKeyChecking", "no"); session.connect(); Cache Quarkus can cache method calls by using as key the tuple (method + arguments). ./mvnw quarkus:add-extension -Dextensions="cache" @io.quarkus.cache.CacheResult(cacheName = "weather-cache") public String getDailyForecast(LocalDate date, String city) {} @CacheInvalidate removes the element represented by the calculated cache key from cache. @CacheInvalidateAll removes all entries from the cache. @CacheKey to speci cally set the arguments b d k d f ll @ApplicationScoped public class CachedBean { @CacheResult(cacheName = "foo") public Object load(Object key) {} @CacheInvalidate(cacheName = "foo") public void invalidate(Object key) {} @CacheInvalidateAll(cacheName = "foo") public void invalidateAll() {} } Programmatic API @Inject CacheManager cacheManager; @Inject @CacheName("my-cache") Cache cache; public Uni<String> getNonBlockingExpensiveValue(Object key) { return cache.get(key, k -> { }); } public String getBlockingExpensiveValue(Object key) { return cache.get(key, k -> { }).await().indefinitely(); (4) } You can disable the caching system by setting quarkus.cache.enabled property to false. This extension uses Caffeine as its underlying caching provider. Each cache can be con gured individually: quarkus.cache.caffeine."foo".initial-capacity=10 quarkus.cache.caffeine."foo".maximum-size=20 quarkus.cache.caffeine."foo".expire-after-write quarkus.cache.caffeine."bar".maximum-size=1000 Full list of con guration properties having quarkus.cache.caffeine. [cache-name] as pre x: initial-capacity Minimum total size for the internal data structures. maximum-size Maximum number of entries the cache may contain. expire-after-write Speci es that each entry should be automatically removed from the cache once a xed duration has elapsed after the entry’s creation or last write expire-after-access Speci es that each entry should be automatically removed from the cache once a xed duration has elapsed after the entry’s creation, or last write. You can multiple cache annotations on a single method. If you see a javax.enterprise.context.ContextNotActiveException, you need to add the quarkus-smallrye-context-propagation extension. Banner Banner is printed by default. It is not an extension but placed in the core. quarkus.banner.path Path is relative to root of the classpath. (default: default_banner.txt) quarkus.banner.enabled Enables banner. (default : true) OptaPlanner Quarkus integrates with OptaPlanner. ./mvnw quarkus:add-extension -Dextensions="quarkus-optaplanner, quarkus-optaplanner-ja ckson" @PlanningSolution public class TimeTable { } @Inject private SolverManager<TimeTable, UUID> solverManager; UUID problemId = UUID.randomUUID(); SolverJob<TimeTable, UUID> solverJob = solverManager.solve (problemId, problem); TimeTable solution = solverJob.getFinalBestSolution(); Possible con guration options pre xed with quarkus.optaplanner: solver-config-xml A classpath resource to read the solver con guration XML. Not mandatory. solver.environment-mode Enable runtime assertions to detect common bugs in your implementation during development. Possible values: FAST_ASSERT, FULL_ASSERT, NON_INTRUSIVE_FULL_ASSERT, NON_REPRODUCIBLE, REPRODUCIBLE. (default: REPRODUCIBLE) solver.move-thread-count
  • 64. Enable multithreaded solving for a single problem. Possible values: MOVE_THREAD_COUNT_NONE, MOVE_THREAD_COUNT_AUTO, a number or formula based on the available processors. (default: MOVE_THREAD_COUNT_NONE) solver.termination.spent-limit How long the solver can run. (ie 5s) solver.termination.unimproved-spent-limit How long the solver can run without nding a new best solution after nding a new best solution. (ie 2h) solver.termination.best-score-limit Terminates the solver when a speci c or higher score has been reached. (ie 0hard/-1000soft) solver-manager.parallel-solver-count The number of solvers that run in parallel. (default: PARALLEL_SOLVER_COUNT_AUTO) Context Propagation ./mvnw quarkus:add-extension -Dextensions="quarkus-smallrye-context-propagation" If using mutiny extension together you already get context propagation for ArC, RESTEasy and transactions. With CompletionStage you need to: @Inject ThreadContext threadContext; @Inject ManagedExecutor managedExecutor; threadContext.withContextCapture(..) .thenApplyAsync(r -> {}, managedExecutor); If you are going to use security in a reactive environment you will likely need Smallrye Content Propagation to propagate the identity throughout the reactive callback. Con guration from HasiCorp Consul You can read runtime con guration from HashiCorp Consul. ./mvnw quarkus:add-extension -Dextensions="consul-config" You need to con gure Consul: quarkus.consul-config.enabled=true quarkus.consul-config.agent.host-port=localhost:8500 quarkus.consul-config.properties-value-keys=config/consul-t est @ConfigProperty(name = "greeting.message") String message; In Consul: "Key": "config/consul-test", "Value": "greeting.message=Hello from Consul" Possible con guration parameters, pre xed with quarkus.consul- config: enabled The application will attempt to look up the con guration from Consul. (default: false) prefix Common pre x that all keys share when looking up the keys from Consul. The pre x is not included in the keys of the user con guration raw-value-keys Keys whose value is a raw string. The keys that end up in the user con guration are the keys speci ed her with '/' replaced by '.' properties-value-keys Keys whose value represents a properties-like le conttent. fail-on-missing-key If the application will not start if any of the con gured con g sources cannot be located. (default: true) trust-store TrustStore to be used containing the SSL certi cate used by Consul agent. trust-store-password Password of TrustStore to be used containing the SSL certi cate used by Consul agent. key-password Password to recover key from KeyStore for SSL client authentication with Consul agent. agent.host-port Consul agent host. (default: localhost:8500) agent.use-https Use HTTPS when communicating with the agent. (default: false) agent.token Consul token to be provided when authentication is enabled. agent.key-store KeyStore (classpath or lesystem) to be used containing the SSL certi cate used by Consul agent. agent.key-store-password Password of KeyStore. agent.trust-certs To trust all certi cates or not. agent.connection-timeout Connection timeout. (default: 10S) agent.read-timeout Reading timeout. (default: 60S) Amazon Alexa You can use Amazon Alexa by adding the extension: ./mvnw quarkus:add-extension -Dextensions="quarkus-amazon-alexa" WebJar Locator To change how you can refer to webjars skipping the version part you can use WebJars locator extension. ./mvnw quarkus:add-extension -Dextensions="webjars-locator" Then the JavaScript location is changed from /webjars/jquery/3.1.1/jquery.min.js to /webjars/jquery/jquery.min.js in your HTML les. Amazon SES mvn quarkus:add-extension -Dextensions="amazon-ses" @Inject software.amazon.awssdk.services.ses.SesClient sesClient; @Inject software.amazon.awssdk.services.ses.SesAsyncClient sesClien t; quarkus.ses.endpoint-override=http://localhost:8012 quarkus.ses.aws.region=us-east-1 quarkus.ses.aws.credentials.type=static quarkus.ses.aws.credentials.static-provider.access-key-id=t est-key quarkus.ses.aws.credentials.static-provider.secret-access-k ey=test-secret You need to set a HTTP client either URL Connection:
  • 65. <dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>url-connection-client</artifactId> </dependency> or Apache HTTP: <dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>apache-client</artifactId> </dependency> quarkus.ses.sync-client.type=apache Or async: <dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>netty-nio-client</artifactId> </dependency> Con guration properties are the same as Amazon DynamoDB but changing the pre x from dynamodb to ses. Jbang Creating an initial script: jbang scripting/quarkusapp.java Adding Quarkus dependencies in script: //DEPS io.quarkus:quarkus-resteasy:{quarkus-version} Put some Quarkus CLI code: @Path("/hello") @ApplicationScoped public class quarkusapp { @GET public String sayHello() { return "hello"; } public static void main(String[] args) { Quarkus.run(args); } } To run the script: jbang quarkusapp.java A Maven goal is provided to scaffold a project: mvn io.quarkus:quarkus-maven-plugin:<version>:create-jbang Narayana LRA The LRA (short for Long Running Action) participant extension is useful in microservice based designs where different services can bene t from a relaxed notion of distributed consistency. The extension integrates with MicroPro le LRA ./mvnw quarkus:add-extension -Dextensions="narayana-lra" The only LRA speci c property is quarkus.lra.coordinator-url=<url> which speci es the HTTP endpoint of an external coordinator, @Path("/") @ApplicationScoped public class SimpleLRAParticipant { @LRA(LRA.Type.REQUIRES_NEW) @Path("/work") @PUT public void doInNewLongRunningAction(@HeaderParam(LRA_HTT P_CONTEXT_HEADER) URI lraId) { } @org.eclipse.microprofile.lra.annotation.Complete @Path("/complete") @PUT public Response completeWork(@HeaderParam(LRA_HTTP_CONTEX T_HEADER) URI lraId, String userData) { return Response.ok(ParticipantStatus.Completed.name()). build(); } @org.eclipse.microprofile.lra.annotation.Compensate @Path("/compensate") @PUT public Response compensateWork(@HeaderParam(LRA_HTTP_CONT EXT_HEADER) URI lraId, String userData) { return Response.ok(ParticipantStatus.Compensated.name ()).build(); } } @LRA can be used in differrent methods, so it’s started in one method and nished in another resource using end attribute: @LRA(value = LRA.Type.REQUIRED, // if there is no incoming context a new one is created cancelOn = { Response.Status.INTERNAL_SERVER_ERROR // cancel on a 500 code }, cancelOnFamily = { Response.Status.Family.CLIENT_ERROR // cancel on an y 4xx code }, end = false) // the LRA will continue to run when the m ethod finishes @LRA(LRA.Type.MANDATORY, // requires an active context befo re method can be executed end = true)
  • 66. Spring DI Quarkus provides a compatibility layer for Spring dependency injection. ./mvnw quarkus:add-extension -Dextensions="quarkus-spring-di" Some examples of what you can do. Notice that annotations are the Spring original ones. @Configuration public class AppConfiguration { @Bean(name = "capitalizeFunction") public StringFunction capitalizer() { return String::toUpperCase; } } Or as a component: @Component("noopFunction") public class NoOpSingleStringFunction implements StringFunction { } Also as a service and injection properties from application.properties. @Service public class MessageProducer { @Value("${greeting.message}") String message; } And you can inject using Autowired or constructor in a component and in a JAX-RS resource too. @Component public class GreeterBean { private final MessageProducer messageProducer; @Autowired @Qualifier("noopFunction") StringFunction noopStringFunction; public GreeterBean(MessageProducer messageProducer) { this.messageProducer = messageProducer; } } Spring Boot Con guration Quarkus provides a compatibility layer for Spring Boot ConfigurationProperties. ./mvnw quarkus:add-extension -Dextensions="quarkus-spring-boot-properties" @ConfigurationProperties("example") public final class ClassProperties { private String value; private AnotherClass anotherClass; // getters/setters } example.value=class-value example.anotherClass.value=true Spring Cloud Con g Client Quarkus integrates Spring Cloud Con g Client and MicroPro le Con g spec. ./mvnw quarkus:add-extension -Dextensions="quarkus-spring-cloud-config-client" You need to con gure the extension: quarkus.spring-cloud-config.uri=http://localhost:8089 quarkus.spring-cloud-config.username=user quarkus.spring-cloud-config.password=pass quarkus.spring-cloud-config.enabled=true @ConfigProperty(name = "greeting.message") String greeting; Pre x is quarkus.spring-cloud-config. uri Base URI where the Spring Cloud Con g Server is available. (default: localhost:8888) username Username to be used if the Con g Server has BASIC Auth enabled. password Password to be used if the Con g Server has BASIC Auth enabled. enabled Enables read con guration from Spring Cloud Con g Server. (default: false) fail-fast True to not start application if cannot access to the server. (default: false) connection-timeout The amount of time to wait when initially establishing a connection before giving up and timing out. (default: 10S) read-timeout The amount of time to wait for a read on a socket before an exception is thrown. (default: 60S) label The label to be used to pull remote con guration properties. Spring Web Quarkus provides a compatibility layer for Spring Web. ./mvnw quarkus:add-extension -Dextensions="quarkus-spring-web" Speci cally supports the REST related features. Notice that infrastructure things like BeanPostProcessor will not be executed. @RestController @RequestMapping("/greeting") public class GreetingController { private final GreetingBean greetingBean; public GreetingController(GreetingBean greetingBean) { this.greetingBean = greetingBean; } @GetMapping("/{name}") public Greeting hello(@PathVariable(name = "name") String name) { return new Greeting(greetingBean.greet(name)); } } Supported annotations are: RestController, RequestMapping, GetMapping, PostMapping, PutMapping, DeleteMapping, PatchMapping, RequestParam, RequestHeader, MatrixVariable, PathVariable, CookieValue, RequestBody, ResponseStatus, ExceptionHandler and RestControllerAdvice. If you scaffold the project with spring-web extension, then Spring Web annotations are sed in the generated project. mvn io.quarkus:quarkus-maven-plugin:2.7.0.Final:create … - Dextensions="spring-web".
  • 67. The next return types are supported: org.springframework.http.ResponseEntity and java.util.Map. The next parameter types are supported: An Exception argument and ServletRequest/HttpServletRequest (adding quarkus-undertow dependency). Spring Data JPA While users are encouraged to use Hibernate ORM with Panache for Relational Database access, Quarkus provides a compatibility layer for Spring Data JPA repositories. ./mvnw quarkus:add-extension -Dextensions="quarkus-spring-data-jpa" INFO: Of course you still need to add the JDBC driver, and con gure it in application.properties. public interface FruitRepository extends CrudRepository<Fruit, Long> { List<Fruit> findByColor(String color); } And then you can inject it either as shown in Spring DI or in Spring Web. Interfaces supported: org.springframework.data.repository.Repository org.springframework.data.repository.CrudRepository org.springframework.data.repository.PagingAndSortingReposito ry org.springframework.data.jpa.repository.JpaRepository. INFO: Generated repositories are automatically annotated with @Transactional. Repository fragments is also supported: public interface PersonRepository extends JpaRepository<Person, Long>, PersonFragment { void makeNameUpperCase(Person person); } User de ned queries: @Query("select m from Movie m where m.rating = ?1") Iterator<Movie> findByRating(String rating); @Modifying @Query("delete from Movie where rating = :rating") void deleteByRating(@Param("rating") String rating); @Query(value = "SELECT COUNT(*), publicationYear FROM Book GROUP BY publicationYear") List<BookCountByYear> findAllByPublicationYear2(); interface BookCountByYear { int getPublicationYear(); Long getCount(); } What is currently unsupported: Methods of org.springframework.data.repository.query.QueryByExampleExec utor QueryDSL support Customizing the base repository java.util.concurrent.Future as return type Native and named queries when using @Query Spring Data Rest While users are encouraged to use REST Data with Panache for the REST data access endpoints generation, Quarkus provides a compatibility layer for Spring Data REST in the form of the spring- data-rest extension. ./mvnw quarkus:add-extension -Dextensions="spring-data-rest" import java.util.Optional; import org.springframework.data.repository.CrudRepository; import org.springframework.data.rest.core.annotation.Reposi toryRestResource; import org.springframework.data.rest.core.annotation.RestRe source; @RepositoryRestResource(exported = false, path = "/my-fruit s") public interface FruitsRepository extends CrudRepository<Fr uit, Long> { @RestResource(exported = true) Optional<Fruit> findById(Long id); @RestResource(exported = true) Iterable<Fruit> findAll(); } The spring-data-jpa extension will generate an implementation for this repository. Then the spring-data-rest extension will generate a REST CRUD resource for it. The following interfaces are supported: org.springframework.data.repository.CrudRepository org.springframework.data.repository.PagingAndSortingReposito ry org.springframework.data.jpa.repository.JpaRepository Spring Security Quarkus provides a compatibility layer for Spring Security. ./mvnw quarkus:add-extension -Dextensions="spring-security" You need to choose a security extension to de ne user, roles, … such as openid-connect, oauth2, properties-file or security-jdbc as seen at RBAC. Then you can use Spring Security annotations to protect the methods: @Secured("admin") @GetMapping public String hello() { return "hello"; } Quarkus provides support for some of the most used features of Spring Security’s @PreAuthorize annotation. Some examples: hasRole @PreAuthorize("hasRole('admin')") @PreAuthorize("hasRole(@roles.USER)") where roles is a bean de ned with @Component annotation and USER is a public eld of the class. hasAnyRole @PreAuthorize("hasAnyRole(@roles.USER, 'view')") Permit and Deny All @PreAuthorize("permitAll()") @PreAuthorize("denyAll()") Anonymous and Authenticated @PreAuthorize("isAnonymous()") @PreAuthorize("isAuthenticated()")
  • 68. Checks if the current logged in user is the same as the username method parameter: @PreAuthorize("#person.name == authentication.principal.use rname") public void doSomethingElse(Person person){} Checks if calling a method if user can access: @PreAuthorize("@personChecker.check(#person, authenticatio n.principal.username)") public void doSomething(Person person){} @Component public class PersonChecker { public boolean check(Person person, String username) { return person.getName().equals(username); } } Combining expressions: @PreAuthorize("hasAnyRole('user', 'admin') AND #user == pri ncipal.username") public void allowedForUser(String user) {} Spring Cache Quarkus provides a compatibility layer for Spring dependency injection. ./mvnw quarkus:add-extension -Dextensions="spring-cache" @org.springframework.cache.annotation.Cacheable("someCache" ) public Greeting greet(String name) {} Quarkus provides compatibility with the following Spring Cache annotations: @Cacheable @CachePut @CacheEvict Spring Schedule Quarkus provides a compatibility layer for Spring Scheduled annotation. ./mvnw quarkus:add-extension -Dextensions="spring-scheduled" @org.springframework.scheduling.annotation.Scheduled(cron= "*/5 * * * * ?") void cronJob() { System.out.println("Cron expression hardcoded"); } @Scheduled(fixedRate = 1000) @Scheduled(cron = "{cron.expr}") Resources https://quarkus.io/guides/ https://www.youtube.com/user/lordofthejars Authors : @alexsotob Java Champion and Director of DevExp at Red Hat 2.7.0.Final