Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
0% found this document useful (0 votes)
109 views

Quarkus Cheat Sheet

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 configuration and allowing to do live coding. The document provides information on getting started with Quarkus, packaging, and running in command mode.

Uploaded by

t9kghq6fxd
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
109 views

Quarkus Cheat Sheet

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 configuration and allowing to do live coding. The document provides information on getting started with Quarkus, packaging, and running in command mode.

Uploaded by

t9kghq6fxd
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 62

Quarkus Cheat-Sheet

What is Quarkus? Or in Kotlin: Command mode


Quarkus is a Kubernetes Native Java stack tailored for GraalVM & plugins { You can de ne the main CLI method to start Quarkus. There are two
OpenJDK HotSpot, crafted from the best of breed Java libraries and java ways, implementing io.quarkus.runtime.QuarkusApplication
standards. Also focused on developer experience, making things } interface or use the Java main method to launch Quarkus.
just work with little to no con guration and allowing to do live apply(plugin = "io.quarkus")
coding. @io.quarkus.runtime.annotations.QuarkusMain
repositories { public class HelloWorldMain implements QuarkusApplication {
Cheat-sheet tested with Quarkus 1.13.0.Final. mavenCentral() @Override
} public int run(String... args) throws Exception {
Getting Started System.out.println("Hello World");
dependencies { return 10;
Quarkus comes with a Maven archetype to scaffold a very simple implementation(enforcedPlatform("io.quarkus:quarkus-bo }
starting project. m:0.26.1")) }
implementation("io.quarkus:quarkus-resteasy")
}
mvn io.quarkus:quarkus-maven-plugin:1.13.0.Final:create \
-DprojectGroupId=org.acme \ run method called when Quarkus starts, and stops when it nishes.
-DprojectArtifactId=getting-started \
-DclassName="org.acme.quickstart.GreetingResource" \ Packaging As Java main :
-Dpath="/hello"

mvn clean package @QuarkusMain


public class JavaMain {
This creates a simple JAX-RS resource called GreetingResource . public static void main(String... args) {
Quarkus.run(HelloWorldMain.class, args);
You need to distribute the -runner.jar le together with quarkus- }
@Path("/hello")
app directory. }
public class GreetingResource {
If quarkus.package.uber-jar property is set to true, then a uber-jar is
@GET created with all dependencies bundled inside the JAR.
@Produces(MediaType.TEXT_PLAIN)
public String hello() { By default, Quarkus uses fast jar packaging, if quarkus.package.type Use @QuarkusMain in only one place.
return "hello"; property is set to legacy-jar then Quarkus creates the old standard
} jar le. Use Quarkus.waitForExit() from the main thread if you want to run
}
application.properties some logic on startup, and then run like a normal application (i.e.
not exit).
quarkus.package.uber-jar=true
Gradle quarkus.package.type=legacy-jar You can inject command line arguments by using
@CommandLineArguments annotation:
There is no way to scaffold a project in Gradle but you only need to
do: To compile to native, you need to set GRAALVM_HOME environment @CommandLineArguments
variable and run the native pro le. String[] args;

plugins {
id 'java' mvn clean package -Pnative
id 'io.quarkus' version '0.26.1' Picocli
} ./gradlew build -Dquarkus.package.type=native
You can use Picocli to implement CLI applications:
repositories {
mavenCentral() ./mvnw quarkus:add-extension
Possible quarkus.package.type are: jar , legacy-jar , uber-jar and
} -Dextensions="picocli"
native .

dependencies {
AppCDS
implementation enforcedPlatform('io.quarkus:quarkus-bo
m:0.26.1') Automatically generate AppCDS as part of the build process set the
implementation 'io.quarkus:quarkus-resteasy' next property: quarkus.package.create-appcds=true .
}
To make use of it, just run java -jar -XX:SharedArchiveFile=app-
cds.jsa myapp.jar .
@CommandLine.Command @CommandLine.Command Dev Mode
public class HelloCommand implements Runnable { public class EntryCommand implements Runnable {
@CommandLine.Option(names = "-c", description = "JDBC c
./mvnw compile quarkus:dev
@CommandLine.Option(names = {"-n", "--name"}, descripti onnection string")
on = "Who will we greet?", defaultValue = "World") String connectionString;
./gradlew quarkusDev
String name;
@Inject
private final GreetingService greetingService; DataSource dataSource;
} Endpoints are registered automatically to provide some basic
public HelloCommand(GreetingService greetingService) { debug info in dev mode:
this.greetingService = greetingService; @ApplicationScoped
HTTP GET /quarkus/arc/beans
} class DatasourceConfiguration {

Query Parameters: scope , beanClass , kind .


@Override @Produces
public void run() { @ApplicationScoped HTTP GET /quarkus/arc/observers
greetingService.sayHello(name); DataSource dataSource(CommandLine.ParseResult parseResu

}
} lt) {
System.out.println(parseResult.matchedOption("c").g
Dev UI
etValue().toString());
}
Quarkus adds a Dev UI console to expose extension features.
}
All classes annotated with picocli.CommandLine.Command are The Dev UI is available in dev mode only and accessible at the
registered as CDI beans. /q/dev endpoint by default.

If only one class annotated with picocli.CommandLine.Command it will Adding Con guration Parameters
be used as entry point. If you want to provide your own
Extensions
@QuarkusMain :
Quarkus comes with extensions to integrate with some libraries To add con guration to your application, Quarkus relies on
such as JSON-B, Camel or MicroPro le spec. To list all available MicroPro le Con g spec.
@QuarkusMain extensions just run:
@CommandLine.Command(name = "demo", mixinStandardHelpOption
@ConfigProperty(name = "greetings.message")
s = true)
./mvnw quarkus:list-extensions String message;
public class ExampleApp implements Runnable, QuarkusApplica
tion {
@ConfigProperty(name = "greetings.message",
defaultValue = "Hello")
@Inject You can use -DsearchPattern=panache to lter out all
String messageWithDefault;
CommandLine.IFactory factory; extensions except the ones matching the expression.
@ConfigProperty(name = "greetings.message")
@Override And to register the extensions into build tool:
Optional<String> optionalMessage;
public void run() {
}
./mvnw quarkus:add-extension -Dextensions=""

@Override Properties can be set (in decreasing priority) as:


./mvnw quarkus:remove-extension -Dextensions=""
public int run(String... args) throws Exception {
return new CommandLine(this, factory).execute(arg System properties ( -Dgreetings.message ).
s);
} extensionsproperty supports CSV format to register more Environment variables ( GREETINGS_MESSAGE ).
} than one extension at once.
Environment le named .env placed in the current working
directory ( GREETING_MESSAGE= ).
Application Lifecycle
Use quarkus.picocli.native-image.processing.enable to false to use External con g directory under the current working directory:
the picocli-codegen annotation processor instead of build steps. You can be noti ed when the application starts/stops by observing config/application.properties .
StartupEvent and ShutdownEvent events.
You can also con gure CDI beans with PicoCLI arguments: Resources src/main/resources/application.properties .

@ApplicationScoped
public class ApplicationLifecycle { greetings.message = Hello World
void onStart(@Observes StartupEvent event) {}
void onStop(@Observes ShutdownEvent event) {}
}
Array , List and Set are supported. The delimiter is comma
( , ) char and \ is the escape char.

Quarkus supports graceful shutdown. By default there is no timeout Con guration Pro les
but can be set by using the quarkus.shutdown.timeout con g
Quarkus allow you to have multiple con guration in the same le
@ConfigProperty(name = "quarkus.application.name") @ConfigProperties(prefix = "greeting", namingStrategy=Namin
( application.properties ).
String applicationName; gStrategy.KEBAB_CASE)
public class GreetingConfiguration {
The syntax for this is %{profile}.config.key=value .
public String message;
public HiddenConfig hidden;
quarkus.http.port=9090 Additional locations
%dev.quarkus.http.port=8181 public static class HiddenConfig {
You can use smallrye.config.locations property to set additional
con guration les. public List<String> recipients;
}
HTTP port will be 9090, unless the 'dev' pro le is active. smallrye.config.locations=config.properties
}

Default pro les are:


And an application.properties mapping previous class:
dev : Activated when in development mode ( quarkus:dev ). or

test : Activated when running tests. greeting.message = hello


java -jar -Dsmallrye.config.locations=config.properties
greeting.hidden.recipients=Jane,John
prod :
The default pro le when not running in development or
test mode
You can embed con guration les inside a dependency by adding
You can create custom pro le names by enabling the pro le either Bean Validation is also supported so properties are validated at
META-INF/microprofile.properties inside the JAR. When dependency
setting quarkus.profile system property or QUARKUS_PROFILE startup time, for example @Size(min = 20) public String message; .
is added to the application, con guration properties are merged
environment variable. with current con guration.
prefix attribute is not mandatory. If not provided, attribute
@Con gProperties is determined by class name (ie GreeetingConfiguration is
quarkus.http.port=9090
translated to greeting or GreetingExtraConfiguration to
%staging.quarkus.http.port=9999
As an alternative to injecting multiple related con guration values, greeting-extra ). The su x of the class is always removed.
you can also use the @io.quarkus.arc.config.ConfigProperties
annotation to group properties. Naming strategy can be changed with property namingStrategy .
And enable it quarkus.profile=staging . KEBAB_CASE (whatever.foo-bar) or VERBATIM (whatever.fooBar).

@ConfigProperties(prefix = "greeting", namingStrategy=Namin annotation can be used to


To get the active pro le programmatically
use @io.quarkus.arc.config.ConfigIgnore
gStrategy.KEBAB_CASE) ignore the injection of con guration elements.
io.quarkus.runtime.configuration.ProfileManager.getActiveProfile() .
public class GreetingConfiguration {
private String message;
You can also set it in the build tool: // getter/setter
@ConfigIgnore
public Integer ignored;
}
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>${surefire-plugin.version}</version>
This class maps greeting.message property de ned in YAML Con g
<configuration>
application.properties .
<systemPropertyVariables> YAML con guration is also supported. The con guration le is
<quarkus.test.profile>foo</quarkus.test.profile> You can inject this class by using CDI @Inject GreetingConfiguration
called application.yaml and you need to register a dependency to
<buildDirectory>${project.build.directory} greeting; .
enable its support:
</buildDirectory>
pom.xml
</systemPropertyVariables> Also you can use an interface approach:
</configuration> <dependency>
@ConfigProperties(prefix = "greeting", namingStrategy=Namin <groupId>io.quarkus</groupId>
gStrategy.KEBAB_CASE) <artifactId>quarkus-config-yaml</artifactId>
public interface GreetingConfiguration { </dependency>
Same for maven-failsafe-plugin .

@ConfigProperty(name = "message")
test { String message();
quarkus:
useJUnitPlatform() String getSuffix();
datasource:
systemProperty "quarkus.test.profile", "foo" url: jdbc:postgresql://localhost:5432/some-database
} driver: org.postgresql.Driver
If property does not follow getter/setter naming convention you
need to use org.eclipse.microprofile.config.inject.ConfigProperty
Special propertiesare set in prod mode: to set it.
Or with pro les:
quarkus.application.version and quarkus.application.name to get
Nested objects are also supporte:
them available at runtime.
Then you need to register the ConfigSource as Java service. Create
"%dev": @ApplicationScoped
a le with the following content:
quarkus: public class GreetingService {
datasource: /META-INF/services/org.eclipse.microprofile.config.spi.ConfigSource
url: jdbc:postgresql://localhost:5432/some-database public String message(String message) {
driver: org.postgresql.Driver com.acme.config.InMemoryConfig return message.toUpperCase();
}
}

In case of subkeys ~ is used to refer to the unpre xed part. Custom Converters

You can implement your own conversion types from String. Scope annotation is mandatory to make the bean discoverable.
quarkus:
Implement org.eclipse.microprofile.config.spi.Converter
http:
interface:
cors: @Inject
~: true GreetingService greetingService;
methods: GET,PUT,POST @Priority(DEFAULT_QUARKUS_CONVERTER_PRIORITY + 100)
public class CustomInstantConverter
implements Converter<Instant> {
Quarkus is designed with Substrate VM in mind. For this
Is equivalent to: @Override reason, we encourage you to use package-private scope
public Instant convert(String value) { instead of private.
quarkus.http.cors=true if ("now".equals(value.trim())) {
quarkus.http.cors.methods=GET,PUT,POST return Instant.now(); Produces
}
return Instant.parse(value); You can also create a factory of an object by using
@javax.enterprise.inject.Produces annotation.
}
Custom Loader
}
You can implement your own ConfigSource to load con guration @Produces
from different places than the default ones provided by Quarkus. @ApplicationScoped
For example, database, custom XML, REST Endpoints, … Message message() {
@Priority annotation is used to override the default
Message m = new Message();
InstantConverter .
You need to create a new class and implement ConfigSource m.setMsn("Hello");
interface: Then you need to register the Converter as Java service. Create a return m;
le with the following content: }

package com.acme.config;
/META-INF/services/org.eclipse.microprofile.config.spi.Converter @Inject
public class InMemoryConfig implements ConfigSource {
Message msg;
com.acme.config.CustomInstantConverter
private Map<String, String> prop = new HashMap<>();

public InMemoryConfig() { Quali ers


// Init properties Undertow Properties
} You can use quali ers to return different implementations of the
Possible parameters with pre x quarkus.servlet : same interface or to customize the con guration of the bean.
@Override
public int getOrdinal() { context-path
// The highest ordinal takes precedence The context path to serve all Servlet context from. (default: / )
return 900;
} default-charset
The default charset to use for reading and writing requests.
@Override
public Map<String, String> getProperties() {
(default: UTF-8 )
return prop;
} Injection
@Override Quarkus is based on CDI 2.0 to implement injection of code. It is
public String getValue(String propertyName) { not fully supported and only a subset of the speci cation is
return prop.get(propertyName); implemented.
}

@Override
public String getName() {
return "MemoryConfigSource";
}
}
To work with JSON-B you need to add a dependency:
@Qualifier @Dependent
@Retention(RUNTIME) public class TracerConfiguration {
@Target({TYPE, METHOD, FIELD, PARAMETER}) @Produces ./mvnw quarkus:add-extension
public @interface Quote { @IfBuildProfile("prod") -Dextensions="io.quarkus:quarkus-resteasy-jsonb"
@Nonbinding String value(); public Tracer realTracer(Reporter reporter, Configurati
} on configuration) {
return new RealTracer(reporter, configuration); Any POJO is marshaled/unmarshalled automatically.
@Produces }
@Quote("") @Produces
public class Sauce {
Message message(InjectionPoint msg) { @DefaultBean
private String name;
Message m = new Message(); public Tracer noopTracer() {
private long scovilleHeatUnits;
m.setMsn( return new NoopTracer();
msg.getAnnotated() }
// getter/setters
.getAnnotation(Quote.class) }
}
.value()
);

Using @io.quarkus.arc.profile.IfBuildProperty annotation, you can


return m; JSON equivalent:
conditionally enable a bean. @io.quarkus.arc.DefaultBean sets the
}
default bean.
{
@Inject "name":"Blair's Ultra Death",
@Quote("Aloha Beach") @Dependent
"scovilleHeatUnits": 1100000
Message message; public class TracerConfiguration {
}
@Produces
@IfBuildProperty(name = "some.tracer.enabled", stringVa
lue = "true")
Quarkus breaks the CDI spec by allowing you to inject public Tracer realTracer(Reporter reporter, Configurati In a POST endpoint example:
quali ed beans without using @Inject annotation. on configuration) {}
@POST
@Quote("Aloha Beach") @Produces @Consumes(MediaType.APPLICATION_JSON)
Message message; @DefaultBean public Response create(Sauce sauce) {
public Tracer noopTracer() {} // Create Sauce
} return Response.created(URI.create(sauce.getId()))
.build();
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. Properties set at runtime have absolutely no effect on the
bean resolution using @IfBuildProperty .
@Quote("") To provide custom JsonBCon g object:
Message message(InjectionPoint msg) { Container-managed Concurrency
} @Dependent
Quarkus provides @io.quarkus.arc.Lock and a built-in interceptor for JsonbConfig jsonConfig(Instance<JsonbConfigCustomizer> cust
@Quote("Aloha Beach") concurrency control. omizers) {
Message message; JsonbConfig config = myJsonbConfig(); // Custom `JsonbC
@Lock onfig`
@ApplicationScoped for (JsonbConfigCustomizer customizer : customizers) {
class SharedService { customizer.customize(config);
Alternatives
}
It is also possible to select alternatives for an application using void addAmount(BigDecimal amout) {
application.properties . } return config;
}
@Lock(value = Lock.Type.READ, time = 1, unit = TimeUni
quarkus.arc.selected-alternatives=org.acme.Foo,org.acme.*,B
t.SECONDS)
ar
BigDecimal getAmount() {
To work with Jackson you need to add:
}
}
Beans by Quarkus Pro le ./mvnw quarkus:add-extension
-Dextensions="quarkus-resteasy-jackson"
Using @io.quarkus.arc.profile.IfBuildProfile and
@io.quarkus.arc.profile.UnlessBuildProfile annotations, you can By default the class is in write mode (so no concurrent calls
conditionally enable a bean. allowed) except when lock type is READ where the method can be
called concurrently if no write operation in process. If you don’t want to use the default ObjectMapper you can customize
it by:
JSON Marshalling/Unmarshalling
Quarkus uses Hibernate Validator to validate input/output of REST
@ApplicationScoped public class NotExpiredValidator
public class CustomObjectMapperConfig {
services and business services using Bean validation spec. implements ConstraintValidator<NotExpired, LocalDate>
@Singleton {
@Produces ./mvnw quarkus:add-extension
public ObjectMapper objectMapper(Instance<ObjectMapperC -Dextensions="io.quarkus:quarkus-hibernate-validator" @Override
ustomizer> customizers) { public boolean isValid(LocalDate value,
ObjectMapper objectMapper = new ObjectMapper(); ConstraintValidatorContext ctx) {
// perform configuration Annotate POJO objects with validator annotations such as: if ( value == null ) return true;
@NotNull , @Digits , @NotBlank , @Min , @Max , … LocalDate today = LocalDate.now();
for (ObjectMapperCustomizer customizer : customizer return ChronoUnit.YEARS.between(today, value) > 0;
s) { }
public class Sauce {
customizer.customize(mapper); }
}
@NotBlank(message = "Name may not be blank")
return objectMapper;
private String name;
}
@Min(0) And use it normally:
}
private long scovilleHeatUnits;
@NotExpired
// getter/setters @JsonbDateFormat(value = "yyyy-MM-dd")
} private LocalDate expired;
Default media type in Quarkus RestEasy is JSON.

XML Marshalling/Unmarshalling To validate an object use @Valid annotation: Manual Validation

To work with JAX-B you need to add a dependency: public Response create(@Valid Sauce sauce) {} You can call the validation process manually instead of relaying to
@Valid by injecting Validator class.

./mvnw quarkus:add-extension
-Dextensions="quarkus-resteasy-jaxb" @Inject
If a validation error is triggered, a violation report is
Validator validator;
generated and serialized as JSON. If you want to
manipulate the output, you need to catch in the code the
Then annotated POJOs are converted to XML. ConstraintViolationException exception.
And use it:
@XmlRootElement
Create Your Custom Constraints
public class Message { Set<ConstraintViolation<Sauce>> violations =
First you need to create the custom annotation: validator.validate(sauce);
}

@GET @Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR,


PARAMETER, TYPE_USE })
@Produces(MediaType.APPLICATION_XML) Localization
public Message hello() { @Retention(RUNTIME)
return message; @Documented You can con gure the based locale for validation messages.
} @Constraint(validatedBy = { NotExpiredValidator.class})
public @interface NotExpired {
quarkus.default-locale=ca-ES
# Supported locales resolved by Accept-Language
String message() default "Sauce must not be expired";
JAXP Class<?>[] groups() default { };
quarkus.locales=en-US,es-ES,fr-FR, ca_ES

Class<? extends Payload>[] payload() default { };


To work with JAX-P you need to add a dependency:
ValidationMessages_ca_ES.properties
}
./mvnw quarkus:add-extension pattern.message=No conforme al patro
-Dextensions="jaxp"
You need to implement the validator logic in a class that
implements ConstraintValidator .
@Pattern(regexp = "A.*", message = "{pattern.message}")
final DocumentBuilder dBuilder = DocumentBuilderFactory.new private String name;
Instance().newDocumentBuilder();
final Document doc = dBuilder.parse(in);
return doc.getDocumentElement().getTextContent();
Bean Validation can be con gured . The pre x is:
quarkus.hibernate-validator .

Validator fail-fast
When fail fast is enabled the validation will stop on the rst The path to log le (default: quarkus.log ) syslog.truncate
constraint violation detected. (default: false ) Message should be truncated (default: true )
file.rotation.max-file-size
method-validation.allow-overriding-parameter-constraints The maximum le size of the log le syslog.block-on-reconnect
De ne whether overriding methods that override constraints Block when attempting to reconnect (default: true )
should throw an exception. (default: false ). file.rotation.max-backup-index
The maximum number of backups to keep (default: 1 ) syslog.async
method-validation.allow-parameter-constraints-on-parallel-methods
Log asynchronously (default: false )
De ne whether parallel methods that de ne constraints should file.rotation.file-suffix
throw an exception. (default: false ). Rotating log le su x. syslog.async.queue-length
The queue length to use before ushing writing (default: 512 )
method-validation.allow-multiple-cascaded-validation-on-return-
file.rotation.rotate-on-boot
values
Indicates rotate logs at bootup (default: true ) syslog.async.overflow
De ne whether more than one constraint on a return value may
be marked for cascading validation are allowed. (default: false ). Action when queue is full (default: BLOCK )
file.async
Log asynchronously (default: false ) You can inject logger instance:
Logging
file.async.queue-length import org.jboss.logging.Logger;
You can con gure how Quarkus logs:
The queue length to use before ushing writing (default: 512 ) import io.quarkus.arc.log.LoggerName;

quarkus.log.console.enable=true file.async.overflow @Inject


quarkus.log.console.level=DEBUG Logger log;
quarkus.log.console.color=false
Action when queue is full (default: BLOCK )

quarkus.log.category."com.lordofthejars".level=DEBUG @LoggerName("foo")
syslog.enable
Logger fooLog;
syslog logging is enabled (default: false )

Pre x is quarkus.log . public void ping() {


syslog.format log.info("Simple!");
category."<category-name>".level The format pattern to use for logging to syslog. Default value: }
Minimum level category (default: INFO ) %d{yyyy-MM-dd HH:mm:ss,SSS} %h %N[%i] %-5p [%c{3.}] (%t) %s%e%n

level syslog.level Gelf ouput


Default minimum level (default: INFO ) The minimum log level to write to syslog (default: ALL )
You can con gure the output to be in GELF format instead of plain
syslog.endpoint text.
console.enabled
Console logging enabled (default: true ) The IP address and port of the syslog server (default:
localhost:514 ) ./mvnw quarkus:add-extension
-Dextensions="quarkus-logging-gelf"
console.format
syslog.app-name
Format pattern to use for logging. Default value:
%d{yyyy-MM-dd HH:mm:ss,SSS} %-5p [%c{3.}] (%t) %s%e%n The app name used when formatting the message in RFC5424
format (default: current process name) handler.gelf.enabled

console.level Enable GELF logging handler (default: false )


syslog.hostname
Minimum log level (default: INFO )
The name of the host the messages are being sent from (default: handler.gelf.host

console.color current hostname) Hostname/IP of Logstash/Graylof. Prepend tcp: for using TCP
protocol. (default: udp:localhost )
Allow color rendering (default: true )
syslog.facility

file.enable Priority of the message as de ned by RFC-5424 and RFC-3164 handler.gelf.port


(default: USER_LEVEL ) The port. (default: 12201 )
File logging enabled (default: false )

syslog.syslog-type handler.gelf.version
file.format
The syslog type of format message (default: RFC5424 ) GELF version. (default: 1.1 )
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
syslog.protocol handler.gelf.extract-stack-trace

file.level Protocol used (default: TCP ) Post Stack-Trace to StackTrace eld. (default: true )

Minimum log level (default: ALL )


syslog.use-counting-framing handler.gelf.stack-trace-throwable-reference

file.path Message pre xed with the size of the message (default false ) Gets the cause level to stack trace. 0 is fulls tack trace. (default:
)
handler.gelf.filter-stack-trace json.print-details You can still use the JAX-RS client without any problem
Stack-Trace ltering. (default: false ) Detailed caller information should be logged (default: false) ClientBuilder.newClient().target(…)

Adding headers
handler.gelf.timestamp-pattern Rest Client
Java Date pattern. (default: yyyy-MM-dd HH:mm:ss,SSS )
You can customize the headers passed by implementing
Quarkus implements MicroPro le Rest Client spec: MicroPro le ClientHeadersFactory annotation:
handler.gelf.level
Log level java.util.logging.Level . (default: ALL ) ./mvnw quarkus:add-extension @RegisterForReflection
-Dextensions="quarkus-rest-client" public class BaggageHeadersFactory
handler.gelf.facility implements ClientHeadersFactory {
Name of the facility. (default: jboss-logmanage ) @Override
To get content from http://worldclockapi.com/api/json/cet/now public MultivaluedMap<String, String> update(
handler.gelf.additional-field.<field>.<subfield> you need to create a service interface: MultivaluedMap<String, String> incomingHeaders,
Post additional elds. quarkus.log.handler.gelf.additional-
MultivaluedMap<String, String> outgoingHeaders) {}
field.field1.type=String
}
@Path("/api")
@RegisterRestClient
handler.gelf.include-full-mdc public interface WorldClockService {
Include all elds from the MDC. And registering it in the client using RegisterClientHeaders
@GET @Path("/json/cet/now") annotation.
@Produces(MediaType.APPLICATION_JSON)
handler.gelf.maximum-message-size
WorldClock getNow(); @RegisterClientHeaders(BaggageHeadersFactory.class)
Maximum message size (in bytes). (default: 8192 )
@RegisterRestClient
@GET public interface WorldClockService {}
handler.gelf.include-log-message-parameters @Path("/json/{where}/now")
Include message parameters from the log event. (default: true ) @Produces(MediaType.APPLICATION_JSON)
WorldClock getSauce(@BeanParam
handler.gelf.include-location WorldClockOptions worldClockOptions); Or statically set:
Include source code location. (default: true )
} @GET
@ClientHeaderParam(name="X-Log-Level", value="ERROR")
JSON output
Response getNow();
You can con gure the output to be in JSON format instead of plain
public class WorldClockOptions {
text.
@HeaderParam("Authorization")
Asynchronous
String auth;
./mvnw quarkus:add-extension
-Dextensions="quarkus-logging-json" A method on client interface can return a CompletionStage class to
@PathParam("where")
be executed asynchronously.
String where;
}
@GET @Path("/json/cet/now")
And the con guration values are pre x with quarkus.log :
@Produces(MediaType.APPLICATION_JSON)
json CompletionStage<WorldClock> getNow();
And con gure the hostname at application.properties :
JSON logging is enabled (default: true).
org.acme.quickstart.WorldClockService/mp-rest/url=
json.pretty-print Reactive
http://worldclockapi.com
JSON output is "pretty-printed" (default: false) Rest Client also integrates with reactive library named Mutiny. To
start using it you need to add the quarkus-rest-client-mutiny .
json.date-format
Injecting the client:
Specify the date format to use (default: the default format) After that, amethodon a client interface can return a
io.smallrye.mutiny.Uni instance.
@RestClient
json.record-delimiter
WorldClockService worldClockService;
Record delimiter to add (default: no delimiter) @GET @Path("/json/cet/now")
@Produces(MediaType.APPLICATION_JSON)
json.zone-id Uni<WorldClock> getNow();
If invokation happens within JAX-RS, you can propagate headers
The time zone ID from incoming to outgoing by using next property.

json.exception-output-type A RESTEasy Reactive-based REST Client extension. You only need


org.eclipse.microprofile.rest.client.propagateHeaders=
The exception output type: detailed , formatted , detailed-and-
to replace the quarkus-rest-client to quarkus-rest-client-reactive .
Authorization,MyCustomHeader
formatted (default: detailed )
Multipart
It is really easy to send multipart form-data with Rest Client. Possible con guration properties:
@QuarkusTest
public class GreetingResourceTest {
%s/mp-rest/trustStore
<dependency>
<groupId>org.jboss.resteasy</groupId> Trust store location de ned with classpath: or file: pre x. @Test
<artifactId>resteasy-multipart-provider</artifactId> public void testHelloEndpoint() {
</dependency> %s/mp-rest/trustStorePassword given()
Trust store password. .when().get("/hello")
.then()
The model object: %s/mp-rest/trustStoreType .statusCode(200)
.body(is("hello"));
Trust store type (default: JKS )
}
import java.io.InputStream;
}
%s/mp-rest/hostnameVerifier
import javax.ws.rs.FormParam; Custom hostname veri er class name. To disable SSL veri cation
import javax.ws.rs.core.MediaType; you can use io.quarkus.restclient.NoopHostnameVerifier .
Test port can be set in quarkus.http.test-port property. Timeout
import %s/mp-rest/keyStore
can be set in quarkus.http.test-timeout property.
org.jboss.resteasy.annotations.providers.multipart.Part
Key store location de ned with classpath: or file: pre x. You can also inject the URL where Quarkus is started:
Type;

%s/mp-rest/keyStorePassword
public class MultipartBody { @TestHTTPResource("index.html")
Key store password. URL url;
@FormParam("file")
@PartType(MediaType.APPLICATION_OCTET_STREAM) %s/mp-rest/keyStoreType
private InputStream file; Key store type (default: JKS )
@TestHTTPEndpoint(GreetingResource.class)
@FormParam("fileName") @TestHTTPResource
Timeout
@PartType(MediaType.TEXT_PLAIN) URL url;
private String name; You can de ne the timeout of the Rest Client:

// getter/setters
org.acme.quickstart.WorldClockService/mp-rest/connectTimeou @QuarkusTest
}
t= @TestHTTPEndpoint(GreetingResource.class)
1000 public class GreetingResourceTest {
org.acme.quickstart.WorldClockService/mp-rest/readTimeout= @Test
And the Rest client interface: 2000 public void testHelloEndpoint() {
given()
import .when().get()
org.jboss.resteasy.annotations.providers.multipart.Mult Instantiate client programmatically .then()
ipartForm; .statusCode(200)
.body(is("hello"));
MovieReviewService reviewSvc = RestClientBuilder.newBuilder
@Path("/echo") }
()
@RegisterRestClient }
.baseUri(apiUri)
public interface MultipartService {
.build(WorldClockService.class);

@POST
Root path is calculated automatically, not necessary to explicitly
@Consumes(MediaType.MULTIPART_FORM_DATA)
set.
@Produces(MediaType.TEXT_PLAIN) Testing
String sendMultipartData(@MultipartForm If you want any changes made to be rolled back at the end ofthe
MultipartBody data); Quarkus archetype adds test dependencies with JUnit 5 and Rest- test you can use the io.quarkus.test.TestTransaction annotation.
Assured library to test REST endpoints.
} QuarkusTestPro le

You can de ne for each Test class a different con guration options.
SSL
This implies that the Quarkus service is restarted.
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
And needs to be registered as Java SPI:
public class MyProfile implements io.quarkus.test.junit.Qua public class MyCustomTestResource
rkusTestProfile { implements QuarkusTestResourceLifecycleManager { META-
INF/services/io.quarkus.test.junit.callback.QuarkusTestBeforeClassCallback

@Override @Override
io.quarkus.it.main.SimpleAnnotationCheckerBeforeClassCallba
public Map<String, String> getConfigOverrides() { public Map<String, String> start() {
ck
return Map.of("greetings.message", "This is a Test" // return system properties that
); // should be set for the running test
} return Collections.emptyMap();
} Mocking
@Override
public String getConfigProfile() { @Override If you need to provide an alternative implementation of a service
return "my-test-profile"; public void stop() { (for testing purposes) you can do it by using CDI @Alternative
} } annotation using it in the test service placed at src/test/java :

@Override // optional @Alternative


public Set<String> tags() { @Override @Priority(1)
return Collections.singleton("test1"); public void inject(Object testInstance) { @ApplicationScoped
} } public class MockExternalService extends ExternalService {}
}
// optional
@QuarkusTest @Override
@TestProfile(MyProfile.class) public int order() { This does not work when using native image testing.
public class MyTestClass { return 0;
} }
} A stereotype annotation io.quarkus.test.Mock is provided declaring
@Alternative , @Priority(1) and @Dependent .

quarkus.test.profile.tags property can be set to limit test Mockito


execution of test pro les. If not set all tests are executed. Returning new system properties implies running parallel
tests in different JVMs. Instead of creating stubs, you can also create mocks of your
quarkus.test.profile.tags=test1 services with mockito. Add the following dependency
And the usage: io.quarkus:quarkus-junit5-mockito :

Quarkus Test Resource @QuarkusTestResource(MyCustomTestResource.class) @InjectMock


public class MyTest { GreetingService greetingService;
You can execute some logic before the rst test run ( start ) and }
execute some logic at the end of the test suite ( stop ). @BeforeEach
public void setup() {
You need to create a class implementing Mockito.when(greetingService.greet()).thenReturn("Hi");
QuarkusTestResourceLifecycleManager interface and register it in the
When using multiple QuarkusTestResource you can set parallel
}
test via @QuarkusTestResource annotation. attribute to true to start them concurrently.
@Path("/hello")
Testing Callbacks
public class ExampleResource {
You can enrich all your @QuarkusTest classes by implementing the
following callback interfaces: @Inject
GreetingService greetingService;
io.quarkus.test.junit.callback.QuarkusTestBeforeClassCallback }

io.quarkus.test.junit.callback.QuarkusTestAfterConstructCall
back
Mock is automatically injected and only valid for the de ned test
class.
io.quarkus.test.junit.callback.QuarkusTestBeforeEachCallback

Also spy is supported:


io.quarkus.test.junit.callback.QuarkusTestAfterEachCallback

@InjectSpy
public class SimpleAnnotationCheckerBeforeClassCallback imp
GreetingService greetingService;
lements QuarkusTestBeforeClassCallback {
@Override
Mockito.verify(greetingService, Mockito.times(1)).greet();
public void beforeClass(Class<?> testClass) {
}
}
REST Client
To Mock REST Client, you need to de ne the interface with includes Persistence
@ApplicationScope : A list of class les to include in the report. (default: ** )
Quarkus works with JPA(Hibernate) as persistence solution. But
@ApplicationScoped excludes also provides an Active Record pattern implementation under
@RegisterRestClient A list of class les to exclude from the report. Panache project.
public interface GreetingService {
} To use database access you need to add Quarkus JDBC drivers
report-location
instead of the original ones. At this time Apache Derby , H2 , MariaDB ,
@InjectMock The location of the report les. (default: jacoco-report ) MySQL , MSSQL and PostgreSQL drivers are supported.
@RestClient
GreetingService greetingService; Native Testing
./mvnw quarkus:add-extension
To test native executables annotate the test with @NativeImageTest .
-Dextensions="io.quarkus:quarkus-hibernate-orm-panache,
Mockito.when(greetingService.hello()).thenReturn("hello fro io.quarkus:quarkus-jdbc-mariadb"
m mockito");
Quarkus Integration Tests

@QuarkusIntegrationTest should be used to launch and test the


artifact produced by the Quarkus build. If the result of a Quarkus @Entity
Interceptors
build is a JAR then the app is launched as java -jar , if native is public class Developer extends PanacheEntity {
Tests are actually full CDI beans, so you can apply CDI interceptors: launched as ./application , if container image is created (JiB,
Docker extensions) is launched as docker run . // id field is implicit

@QuarkusTest
public String name;
@Stereotype
}
@Transactional
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface TransactionalQuarkusTest { And con guration in src/main/resources/application.properties :
}
quarkus.datasource.jdbc.url=jdbc:mariadb://localhost:3306/m
@TransactionalQuarkusTest ydb
public class TestStereotypeTestCase {} quarkus.datasource.db-kind=mariadb
quarkus.datasource.username=developer
quarkus.datasource.password=developer
Test Coverage quarkus.hibernate-orm.database.generation=update

Due the nature of Quarkus to calculate correctly the coverage


information with JaCoCo, you might need o ine instrumentation. List of datasource parameters.

./mvnw quarkus:add-extension quarkus.datasource as pre x is skipped in the next table.


-Dextensions="quarkus-jacoco "
db-kind
Built-in datasource kinds so the JDBC driver is resolved
Possible con guration parameters pre xed quarkus.jacoco :
automatically. Possible values: derby , h2 , mariadb , mssql , mysql ,
postgresql , db2 .
data-file
username
The jacoco data le. (default: jacoco-quarkus.exec )
Username to access.
report
password
If Quarkus should generate the Jacoco report. (default: true )
Password to access.
output-encoding
driver
Encoding of the generated reports. (default: UTF-8 )
JDBC Driver class. It is not necessary to set if db-kind used.
title
credentials-provider
Name of the root node HTML report pages.
Sets a custom credential provider name.
footer
credentials-provider-name
Footer text used in HTML report pages.
It is the @Named value of the credentials provider bean. Not
source-encoding necessary if only one implementation.
Encoding of the source les (default: UTF-8 )
jdbc.url dialect Number of rows fetched at a time.
The datasource URL. Class name of the Hibernate ORM dialect.
jdbc.statement-batch-size
jdbc.min-size dialect.storage-engine Number of updates sent at a time.
The datasource pool minimum size. (default: 0 ) The storage engine when the dialect supports multiple storage
engines. log.sql
jdbc.max-size Show SQL logs (default: false )
The datasource pool maximum size. (default: 20 ) sql-load-script
Name of the le containing the SQL statements to execute when log.jdbc-warnings
jdbc.initial-size starts. no-file force Hibernate to skip SQL import. (default: statistics
import.sql )
The initial size of the pool. Enable statiscs collection. (default: false )

batch-fetch-size
jdbc.background-validation-interval physical-naming-strategy
The interval at which we validate idle connections in the The size of the batches. (default: -1 disabled) Class name of the Hibernate PhysicalNamingStrategy
background. (default: 2M ) implementation.
maxFetchDepth

jdbc.acquisition-timeout The maximum depth of outer join fetch tree for single-ended globally-quoted-identifiers
The timeout before cancelling the acquisition of a new associations. Should quote all identi ers. (default: false )
connection. (default: 5 )
multitenant
metrics-enabled
jdbc.leak-detection-interval De nes the method for multi-tenancy. Possible values: DATABASE ,
Metrics published with smallrye-metrics extension (default:
NONE , SCHEMA . (default: NONE )
The interval at which we check for connection leaks. false )

multitenant-schema-datasource
jdbc.idle-removal-interval second-level-caching-enabled
The interval at which we try to remove idle connections. (default: De nes the name of the data source to use in case of SCHEMA Enable/Disable 2nd level cache. (default: true )
5M )
approach.
Database operations:
query.query-plan-cache-max-size
jdbc.max-lifetime
The max lifetime of a connection. The maximum size of the query plan cache. // Insert
Developer developer = new Developer();
query.default-null-ordering developer.name = "Alex";
jdbc.transaction-isolation-level
The transaction isolation level. Possible values: UNDEFINED , NONE , Default precedence of null values in ORDER BY . Possible values: developer.persist();
none , first , last . (default: none )
READ_UNCOMMITTED , READ_COMMITTED , REPEATABLE_READ , SERIALIZABLE .
// Find All
database.generation Developer.findAll().list();
jdbc.detect-statement-leaks
Warn when a connection is returned to the pool without the Database schema is generation. Possible values: none , create ,
drop-and-create , drop , update . (default: none )
// Hibernate Filters
application having closed all open statements. (default: true ) Person.findAll().filter("Person.hasName", Parameters.with(
"name", "Alex"));
database.generation.halt-on-error
jdbc.new-connection-sql
Query executed when rst using a connection. Stop on the rst error when applying the schema. (default: false )
// Find By Query
Developer.find("name", "Alex").firstResult();
database.generation.create-schemas
jdbc.validation-query-sql
Query executed to validate a connection. Hibernate ORM should create the schemas automatically (for // Delete
databases supporting them). Developer developer = new Developer();
developer.id = 1;
jdbc.pooling-enabled
database.default-catalog developer.delete();
Disable pooling to prevent reuse of Connections. (default: true )
Default catalog.
Person.deleteById(id);
jdbc.enable-metrics // Delete By Query
database.default-schema
Enable datasource metrics collection when using quarkus- long numberOfDeleted = Developer.delete("name", "Alex");
smallrye-metrics extension.
Default Schema.

database.charset
jdbc.additional-jdbc-properties.<extraProperty>
Remember to annotate methods with @Transactional annotation to
Unspeci ed properties to be passed to the JDBC driver when Charset.
make changes persisted in the database.
creating new connections.
jdbc.timezone If queries start with the keyword from then they are treated as HQL
Hibernate con guration properties. Pre x quarkus.hibernate-orm is Time Zone JDBC driver. query, if not then next short form is supported:
skipped.
jdbc.statement-fetch-size order by which expands to from EntityName order by …
<columnName> which expands to from EntityName where count : String , [ Object… , Map<String, Object> , Parameters ] If entities are de ned in external JAR, you need to enable in these
<columnName>=? Number of entities meeting given query with parameters set. projects the Jandex plugin in project.

<query> which is expanded to from EntityName where <query>


Enables a Hibernate lter during fetching of results for this query. <plugin>
<groupId>org.jboss.jandex</groupId>
Static Methods
deleteAll <artifactId>jandex-maven-plugin</artifactId>
findById : Object Number of deleted entities. <version>1.0.3</version>
<executions>
Returns object or null if not found. Overloaded version with <execution>
delete : String , [ Object… , Map<String, Object> , Parameters ]
LockModeType is provided.
<id>make-index</id>
Number of deleted entities meeting given query with parameters
<goals>
findByIdOptional : Optional<Object> set.
<goal>jandex</goal>
Returns object or java.util.Optional . </goals>
deleteById : boolean , [ Object ]
</execution>
find : String , [ Object… , Map<String, Object> , Parameters ] Delete by id. Returns if deleted or not. </executions>
Lists of entities meeting given query with parameters set. <dependencies>
Returning a PanacheQuery . persist : [ Iterable , Steram , Object… ] <dependency>
Persist object. <groupId>org.jboss</groupId>
find : String , Sort , [ Object… , Map<String, Object> , Parameters ] <artifactId>jandex</artifactId>
In case of using streams, remember to close them or use a <version>2.1.1.Final</version>
Lists of entities meeting given query with parameters set sorted </dependency>
by Sort attribute/s. Returning a PanacheQuery . try/catch block: try (Stream<Person> persons = Person.streamAll()) .
</dependencies>
find methods de nes a withLock(LockModeType) to de ne </plugin>
findAll
the lock type and withHint(QueryHints.HINT_CACHEABLE,
Finds all entities. Returning a PanacheQuery .
"true") to de ne hints.
Panache includes an annotation processor that enhance your
findAll : Sort Named Queries entities. If you disable annotation processors you might need to
Finds all entities sorted by Sort attribute/s. Returning a create a marker le on Panache archives at META-INF/panache-
PanacheQuery . @Entity archive.marker manually.
@NamedQuery(name = "Person.getByName", query = "from Person
list : String , [ Object… , Map<String, Object> , Parameters ] where name = :name") Testing
Lists of entities meeting given query with parameters set. public class Person extends PanacheEntity {
Returning a List . To mock using active record pattern:
public static Person findByName(String name){
list : String , Sort , [ Object… , Map<String, Object> , Parameters ] return find("#Person.getByName", name).firstResult <dependency>
(); <groupId>io.quarkus</groupId>
Lists of entities meeting given query with parameters set sorted
} <artifactId>quarkus-panache-mock</artifactId>
by Sort attribute/s. Returning a List .
} <scope>test</scope>
</dependency>
listAll
Finds all entities. Returning a List .
Pagination
listAll : Sort @Test
PanacheQuery<Person> livingPersons = Person public void testPanacheMocking() {
Finds all entities sorted by Sort attribute/s. Returning a List .
.find("status", Status.Alive); PanacheMock.mock(Person.class);
livingPersons.page(Page.ofSize(25));
stream : String , [ Object… , Map<String, Object> , Parameters ]
Mockito.when(Person.count()).thenReturn(23l);
java.util.stream.Stream of entities meeting given query with // get the first page Assertions.assertEquals(23, Person.count());
parameters set. List<Person> firstPage = livingPersons.list(); PanacheMock.verify(Person.class, Mockito.times(1)).coun
// get the second page t();
stream : String , Sort , [ Object… , Map<String, Object> , Parameters ] List<Person> secondPage = livingPersons.nextPage().list(); }
java.util.stream.Stream of entities meeting given query with
parameters set sorted by Sort attribute/s.
Range DevServices
streamAll
java.util.stream.Stream of all entities. When testing or running in dev mode Quarkus can even provide you
PanacheQuery<Person> livingPersons = Person
with a zero con g database out of the box. Depending on your
.find("status", Status.Alive);
streamAll : Sort database type you may need docker installed in order to use this
List<Person> secondRange = livingPersons.range(25, 49).list
feature.
java.util.stream.Stream of all entities sorted by Sort attribute/s. ();

The following open source databases:


count
Number of entities You cannot mix pagination and range Postgresql (container)
MySQL (container) @Transactional(REQUIRES_NEW) : starts a transaction if none was
# default
started; if an existing one was started, suspends it and starts a
quarkus.datasource.db-kind=h2
MariaDB (container) new one for the boundary of that method.
quarkus.datasource.jdbc.url=jdbc:h2:tcp://localhost/mem:def
H2 (in-process) ault
@Transactional(MANDATORY) : fails if no transaction was started ;
....
works within the existing transaction otherwise.
Apache Derby (in-process) # users datasource
quarkus.datasource.users.devservices=false @Transactional(SUPPORTS) :if a transaction was started, joins it ;
To use DevServices don’t con gure a database URL, username and quarkus.datasource.users.db-kind=h2 otherwise works with no transaction.
password, Quarkus will provide the database and you can just start quarkus.datasource.users.jdbc.url=jdbc:h2:tcp://localhost/m
coding without worrying about con g. em:users @Transactional(NOT_SUPPORTED) :if a transaction was started,
suspends it and works with no transaction for the boundary of
quarkus.datasource.db-kind=mariadb the method; otherwise works with no transaction.
%prod.quarkus.datasource.jdbc.url=jdbc:mariadb://db:3306/my Notice that after datasource you set the datasource name, in
@Transactional(NEVER) :
if a transaction was started, raises an
db previous case users .
%prod.quarkus.datasource.username=developer exception; otherwise works with no transaction.
%prod.quarkus.datasource.password=developer You can inject then AgroalDataSource with
You can con gure the default transaction timeout using
io.quarkus.agroal.DataSource .
quarkus.transaction-manager.default-transaction-timeout
con guration property. By default it is set to 60 seconds.
Possible con guration values pre xed with quarkus.datasource : @DataSource("users")
AgroalDataSource dataSource1; You can set a timeout property, in seconds, that applies to
devservices transactions created within the annotated method by using
If devservices is enabled or not. (default: true ) @TransactionConfiguration annotation.
Flushing
devservices.image-name @Transactional
The container image name to use instead of the default one. You can force ush operation by calling .flush() or @TransactionConfiguration(timeout=40)
.persistAndFlush() to make it in a single call. public void createDeveloper() {}
devservices.properties
This ush is less e cient and you still need to commit
Generic properties that are added to the database connection transaction.
URL. If you want more control over transactions you can inject
UserTransaction and use a programmatic way.
Testing
DAO pattern
There is a Quarkus Test Resource that starts and stops H2 server @Inject UserTransaction transaction
Also supports DAO pattern with PanacheRepository<TYPE> .
before and after test suite.
transaction.begin();
@ApplicationScoped Register dependency io.quarkus:quarkus-test-h2:test . transaction.commit();
public class DeveloperRepository transaction.rollback();
implements PanacheRepository<Person> { And annotate the test:
public Person findByName(String name){
return find("name", name).firstResult(); @QuarkusTestResource(H2DatabaseTestResource.class) You can implement your custom credentials provider (ie Azure
} public class FlywayTestResources { KeyVault) to provide a username/password for the database
} } connection. Name information is not necessary if there is only one
custom credential provider.

EntityManager You can inject EntityManager in your classes: Transactions

@Inject The easiest way to de ne your transaction boundaries is to use the


EntityManager em; @Transactional annotation.

@Inject Transactions are mandatory in case of none idempotent


org.hibernate.Session session; operations.

@Inject @Transactional
org.hibernate.SessionFactory sessionFactory; public void createDeveloper() {}

em.persist(car);
You can control the transaction scope:

Multiple datasources @Transactional(REQUIRED) (default): starts a transaction if none


was started, stays with the existing one otherwise.
You can register more than one datasource.
get(@PathParam("id")) , list , add(Developer) ,
@ApplicationScoped quarkus.hibernate-orm.database.generation=none
update(@PathParam("id"), Developer) , delete(@PathParam("id"))
@Unremovable
@Named("my-credentials-provider") quarkus.hibernate-orm.multitenant=DATABASE
You can customize these defaults by using @ResourceProperties and
public class CustomCredentialsProvider implements Credentia
@MethodProperties annotations.
lsProvider { # default tenant
@Inject quarkus.datasource.base.db-kind=postgresql
Config config; quarkus.datasource.base.username=quarkus_test @ResourceProperties(hal = true, path = "my-developer", halC
... ollectionName = "dev-collections")
@Override # Tenant 'mycompany' public interface DeveloperResource extends PanacheEntityRes
public Properties getCredentials(String credentials quarkus.datasource.mycompany.db-kind=postgresql ource<Developer, Long> {
ProviderName) { quarkus.datasource.mycompany.username=mycompany @MethodProperties(path = "all")
quarkus.flyway.mycompany.locations=classpath:database/mycom List<Developer> list();
properties.put(CredentialsProvider.USER_PROPERTY_NA pany @MethodProperties(exposed = false)
ME, "hibernate_orm_test"); ... void delete(Long id);
properties.put(CredentialsProvider.PASSWORD }
_PROPERTY_NAME, "hibernate_orm_test");

If you need more dynamic approach implement: @ApplicationScoped


}
io.quarkus.hibernate.orm.runtime.tenant.TenantConnectionResolver If hal is true , you need to send the Accept: application/hal+json
} HTTP header to get the response.
Hibernate Envers
Hibernate Reactive
quarkus.datasource.credentials-provider= Quarkus supports Hibernate Envers.
custom ./mvnw quarkus:add-extension
quarkus.datasource.credentials-provider-name= ./mvnw quarkus:add-extension -Dextensions="quarkus-hibernate-reactive, quarkus-resteas
my-credentials-provider -Dextensions="hibernate-envers" y-mutiny, "

Hibernate Multitenancy Also you need to add the reactive driver (ie
REST Data Panache client ).
quarkus-reactive-pg-

Multitenancy is supported using Schema or Database approach.


First you need to de ne how tenant is identi ed: REST Data with Panache extension can generate the basic CRUD You can use: org.hibernate.reactive.mutiny.Mutiny or
endpoints for your entities and repositories. org.hibernate.reactive.stage.Stage .
@RequestScoped
@Unremovable ./mvnw quarkus:add-extension @Entity
public class CustomTenantResolver implements TenantResolver -Dextensions="hibernate-orm-rest-data-panache" @Table(name = "dev")
{ public class Developer {
}
@Inject You also need to add the JDBC driver extension and a JSON
RoutingContext context; Marshaller (ie resteasy-jackson ). @Inject
CompletionStage<Stage.Session> stageSession;
@Override Then you can de ne interfaces for de ning endpoints:
public String getDefaultTenantId() { @Inject
return "base"; In case of Active Record pattern: Uni<Mutiny.Session> mutinySession;
}
public interface DeveloperResource extends PanacheEntityRes public Uni<Long> reactivePersist() {
@Override ource<Developer, Long> { return mutinySession
public String resolveTenantId() { } .flatMap(s -> s.persist(new Developer(1, "Alex"))
} .flatMap(v -> session.flush())
....
}
In case of Repository:
}

public interface DeveloperResource extends PanacheRepositor public CompletionStage<Developer> reactiveFind() {


Schema approach yResource<DeveloperRepository, Developer, Long> { return stageSession
} .thenCompose(session -> {
quarkus.hibernate-orm.database.generation=none session.find(Developer.class, 1);
});
quarkus.hibernate-orm.multitenant=SCHEMA
Quarkus will generate automatically the implementation for you }
following the next rules:

Database approach Default path is a hyphenated lowercase resource name


without a su x of or In nispan
Quarkus integrates with In nispan:
@Produces
Con guration in infinispan.xml :
FileDescriptorSource bookProtoDefinition() {
./mvnw quarkus:add-extension return FileDescriptorSource
-Dextensions="infinispan-client" .fromString("library.proto", <local-cache name="quarkus-transaction">
"package book_sample;\n" + <transaction
"message Author {\n" + transaction-manager-lookup=
" required string name = 1;\n" + "org.infinispan.transaction.lookup.JBossStandaloneJ
Serialization uses a library called Protostream. TAManagerLookup"/>
" required string surname = 2;\n" +
</local-cache>
Annotation based "}");
}

@ProtoFactory
public Author(String name, String surname) { Set con guration le location in application.properties :
this.name = name; Marshaller
this.surname = surname; quarkus.infinispan-embedded.xml-config=infinispan.xml
} Using org.infinispan.protostream.MessageMarshaller interface.

@ProtoField(number = 1) public class AuthorMarshaller And you can inject the main entry point for the cache:
public String getName() { implements MessageMarshaller<Author> {
return name;
} @Inject
@Override
org.infinispan.manager.EmbeddedCacheManager cacheManager;
public String getTypeName() {
@ProtoField(number = 2) return "book_sample.Author";
public String getSurname() { }

}
return surname;
Redis
@Override
public Class<? extends Author> getJavaClass() {
Quarkus integrates with Redis.
return Author.class;
Initializer to set con guration settings. }
./mvnw quarkus:add-extension
-Dextensions="redis-client"
@Override
@AutoProtoSchemaBuilder(includeClasses =
public void writeTo(ProtoStreamWriter writer,
{ Book.class, Author.class },
Author author) throws IOException {
schemaPackageName = "book_sample")
writer.writeString("name", author.getName()); Con gure Redis location:
interface BookContextInitializer
writer.writeString("surname", author.getSurname());
extends SerializationContextInitializer {
} quarkus.redis.hosts=localhost:6379
}

@Override
public Author readFrom(ProtoStreamReader reader)
User written based throws IOException { You can use synchronous or reactive clients:
String name = reader.readString("name");
There are three ways to create your schema: String surname = reader.readString("surname"); @Inject
return new Author(name, surname); RedisClient redisClient;
Proto le }
} @Inject
Creates a .proto le in the META-INF directory.
ReactiveRedisClient reactiveRedisClient;

package book_sample;
And producing the marshaller:
message Author {
required string name = 1; @Produces
required string surname = 2; MessageMarshaller authorMarshaller() {
} return new AuthorMarshaller();
}

In case of having a Collection eld you need to use the repeated key
(ie repeated Author authors = 4 ). In nispan Embedded

In code ./mvnw quarkus:add-extension


-Dextensions="infinispan-embeddedy"
Setting proto schema directly in a produced bean.
void increment(String key, Integer incrementBy) { Flyway sql-migration-prefix

redisClient.incrby(key, incrementBy.toString()); Pre x for versioned SQL migrations (default: V )


} Quarkus integrates with Flyway to help you on database schema
migrations. repeatable-sql-migration-prefix:: Pre x for repeatable SQL
Uni<List<String>> keys() { migrations (default: R )
return reactiveRedisClient ./mvnw quarkus:add-extension
.keys("*") baseline-on-migrate
-Dextensions="quarkus-flyway"
.map(response -> { Only migrations above baseline-version will then be applied
List<String> result = new ArrayList<>();
for (Response r : response) { baseline-version
result.add(r.toString());
Then place migration les to the migrations folder
( classpath:db/migration ). Version to tag an existing schema with when executing baseline
}
(default: 1)
return result;
You can inject org.flywaydb.core.Flyway to programmatically
});
execute the migration. baseline-description
}
Description to tag an existing schema with when executing
@Inject baseline (default: Flyway Baseline )
Flyway flyway;
Multiple Redis Clients validate-on-migrate
flyway.migrate(); Validate the applied migrations against the available ones
quarkus.redis.hosts = localhost:6379
(default: true )
quarkus.redis.second.hosts = localhost:6379

Or can be automatically executed by setting migrate-at-start placeholder-prefix


property to true . Pre x of every placeholder (default: ${ )
@Inject
RedisClient defaultRedisClient; quarkus.flyway.migrate-at-start=true placeholder-suffix
Su x of every placeholder (default: } )
@Inject
@RedisClientName("second")
List of Flyway parameters. callbacks
RedisClient redisClient2;
Comma-separated list of fully quali ed class names of Callback
quarkus.flyway as pre x is skipped in the next table. implementations.
clean-at-start
List of Redis parameters. ignore-future-migrations
Execute Flyway clean command (default: false )
quarkus.redis as pre x is skipped in the next table. Ignore future migrations when reading the history table.
migrate-at-start
health.enabled Multiple Datasources
Flyway migration automatically (default: false )
Health check is published in case the smallrye-health extension
To use multiple datasource in Flyway you just need to add the
is present. (default: true ) locations datasource name just after the flyway property:
CSV locations to scan recursively for migrations. Supported
password
pre xes classpath and filesystem (default: quarkus.datasource.users.jdbc.url=jdbc:h2:tcp://localhost/m
The Redis password. classpath:db/migration ). em:users
quarkus.datasource.inventory.jdbc.url=jdbc:h2:tcp://localho
hosts connect-retries st/mem:inventory
The Redis hosts. (default: localhost:6379 ) The maximum number of retries when attempting to connect # ...
(default: 0)
database quarkus.flyway.users.schemas=USERS_TEST_SCHEMA
The Redis database. schemas
quarkus.flyway.inventory.schemas=INVENTORY_TEST_SCHEMA
# ...
CSV case-sensitive list of schemas managed (default: none)
timeout

The maximum delay to wait before a blocking command to redis table


server times out. (default: 10s ) The name of
Flyway’s schema history table (default: Liquibase
flyway_schema_history )
ssl Quarkus integrates with Liquibase to help you on database schema
Enables or disables the SSL on connect. out-of-order migrations.
Allows migrations to be run "out of order".
clinet-type ./mvnw quarkus:add-extension
The Redis client type. Possible values: standalone , cluster , ignore-missing-migrations -Dextensions="quarkus-liquibase"
sentinel (default: standalone ) Ignore missing migrations when reading the history table.
Then place changelog les to the ( src/main/resources/db ) folder. liquibase-catalog-name You need to de ne the analyzers and normalizers de ned in
The liquibase tables catalog name. annotations. You only need to implement
You can inject org.quarkus.liquibase.LiquibaseFactory to ElasticsearchAnalysisConfigurer interface and con gure it.
programmatically execute the migration.
liquibase-schema-name
The liquibase tables schema name. public class MyQuarkusAnalysisConfigurer
@Inject implements ElasticsearchAnalysisConfigurer {
LiquibaseFactory liquibaseFactory;
liquibase-tablespace-name
@Override
try (Liquibase liquibase = liquibaseFactory.createLiquibase The liquibase tables tablespace name. public void configure(
()) { ElasticsearchAnalysisDefinitionContainerContext ct
... Multiple Datasources x)
} {
To use multiple datasource in Liquibase you just need to add the
ctx.analyzer("english").custom()
datasource name just after the liquibase property: .withTokenizer("standard")
Or can be automatically executed by setting migrate-at-start .withTokenFilters("asciifolding",
quarkus.datasource.users.jdbc.url=jdbc:h2:tcp://localhost/m "lowercase", "porter_stem");
property to true .
em:users
quarkus.datasource.inventory.jdbc.url=jdbc:h2:tcp://localho ctx.normalizer("sort").custom()
quarkus.liquibase.migrate-at-start=true st/mem:inventory .withTokenFilters("asciifolding", "lowercase");
# ... }
}
List of Liquibase parameters. quarkus.liquibase.users.schemas=USERS_TEST_SCHEMA
quarkus.liquibase.inventory.schemas=INVENTORY_TEST_SCHEMA
quarkus.liquibase as pre x is skipped in the next table. # ...
Use Hibernate Search in REST service:
change-log
The change log le. XML , YAML , JSON , SQL formats supported. public class LibraryResource {
(default: db/changeLog.xml ) Hibernate Search
@Inject
change-log-parameters."<parameter-name>" Quarkus integrates with Elasticsearch to provide a full-featured full- EntityManager em;
text search using Hibernate Search API.
Liquibase changelog parameters. @Transactional
./mvnw quarkus:add-extension public List<Author> searchAuthors(
migrate-at-start @QueryParam("pattern") String pattern) {
-Dextensions="quarkus-hibernate-search-elasticsearch"
The migrate at start ag. (default: false ) return Search.getSearchSession(em)
.search(Author.class)
validate-on-migrate .predicate(f ->
You need to annotate your model with Hibernate Search API to pattern == null || pattern.isEmpty() ?
The validate on update ag. (default: false )
index it: f.matchAll() :
f.simpleQueryString()
clean-at-start
@Entity .onFields("firstName",
The clean at start ag. (default: false )
@Indexed "lastName", "books.title")
public class Author extends PanacheEntity { .matching(pattern)
contexts )
The list of contexts. @FullTextField(analyzer = "english") .sort(f -> f.byField("lastName_sort")
public String bio; .then().byField("firstName_sort"))
labels .fetchHits();
@FullTextField(analyzer = "name") }
The list of labels.
@KeywordField(name = "firstName_sort",
sortable = Sortable.YES,
database-change-log-table-name
normalizer = "sort")
The database change log lock table name. (default: public String firstName;
When not using Hibernate ORM, index data using
DATABASECHANGELOG ) Search.getSearchSession(em).createIndexer()

@OneToMany
.startAndWait() at startup time.
database-change-log-lock-table-name @IndexedEmbedded
Con gure the extension in application.properties :
The database change log lock table name. (default: public List<Book> books;
DATABASECHANGELOGLOCK )
}
default-catalog-name
The default catalog name.

default-schema-name It is not mandatory to use Panache.


The default schema name
quarkus.hibernate-search.elasticsearch.version=7
When enabled, re-indexing of is skipped if the changes are on @Inject
properties that are not used when indexing.
quarkus.hibernate-search.elasticsearch. DynamoDbClient dynamoDB;
analysis-configurer=MyQuarkusAnalysisConfigurer
index-defaults.lifecycle.strategy
quarkus.hibernate-search.elasticsearch.
automatic-indexing.synchronization-strategy=searchable Index lifecycle ( none , validate , update , create , drop-and-create ,
To use asycnhronous client with Mutiny:
quarkus.hibernate-search.elasticsearch. drop-abd-create-drop )
index-defaults.lifecycle.strategy=drop-and-create
quarkus.hibernate-search.elasticsearch. index-defaults.lifecycle.required-status
./mvnw quarkus:add-extension
index-defaults.lifecycle.required-status=yellow -Dextensions="quarkus-amazon-dynamodb, resteasy-mutiny"
Minimal cluster status ( green , yellow , red )

index-defaults.lifecycle.required-status-wait-timeout
List of Hibernate-Elasticsearch properties pre xed with Waiting time before failing the bootstrap. @Inject
quarkus.hibernate-search.elasticsearch : DynamoDbAsyncClient dynamoDB;
index-defaults.refresh-after-write
backends Uni.createFrom().completionStage(() -> dynamoDB.scan(scanRe
Set if index should be refreshed after writes.
Map of con guration of additional backends. quest()))....

Possible annotations:
version
Version of Elasticsearch @Indexed To use it as a local DynamoDB instance:
Register entity as full text index
analysis-configurer quarkus.dynamodb.region=
Class or name of the neab used to con gure. @FullTextField eu-central-1
Full text search. Need to set an analyzer to split tokens. quarkus.dynamodb.endpoint-override=
hosts http://localhost:8000
quarkus.dynamodb.credentials.type=STATIC
List of Elasticsearch servers hosts. @KeywordField
quarkus.dynamodb.credentials.static-provider
The string is kept as one single token but can be normalized. .access-key-id=test-key
username
quarkus.dynamodb.credentials.static-provider
Username for auth. IndexedEmbedded
.secret-access-key=test-secret
Include the Book elds into the Author index.
password

Password for auth. @ContainerExtraction


If you want to work with an AWS account, you’d need to set it with:
Sets how to extract a value from container, e.g from a Map .
connection-timeout
quarkus.dynamodb.region=<YOUR_REGION>
Duration of connection timeout. @DocumentId
quarkus.dynamodb.credentials.type=DEFAULT
Map an unusual entity identi er to a document identi er.
max-connections
Max number of connections to servers. @GenericField
DEFAULT credentials provider chain:
Full text index for any supported type.
max-connections-per-route System properties aws.accessKeyId , aws.secretKey
Max number of connections to server. @IdentifierBridgeRef
Env. Varables AWS_ACCESS_KEY_ID , AWS_SECRET_ACCESS_KEY
Reference to the identi er bridge to use for a @DocumentId .
indexes
Credentials pro le ~/.aws/credentials
Per-index speci c con guration. @IndexingDependency

How a dependency of the indexing process to a property should Credentials through the Amazon EC2 container service if the
discovery.enabled affect automatic reindexing. AWS_CONTAINER_CREDENTIALS_RELATIVE_URI set
Enables automatic discovery.
@ObjectPath Credentials through Amazon EC2 metadata service.
discovery.refresh-interval @ScaledNumberField Con guration parameters pre xed with quarkus.dynamodb :
Refresh interval of node list. For java.math.BigDecimal or java.math.BigInteger that you need
higher precision.
discovery.default-scheme Parameter Default Description
Scheme to be used for the new nodes. Amazon DynamoDB
Endpoint discovery
automatic-indexing.synchronization-strategy Quarkus integrates with https://aws.amazon.com/dynamodb/: enable-endpoint- for a service API that
Status for which you wait before considering the operation discovery
false
supports endpoint
completed ( queued , committed or searchable ). ./mvnw quarkus:add-extension discovery.
-Dextensions="quarkus-amazon-dynamodb"
automatic-indexing.enable-dirty-check
endpoint-override Con gure the Parameter Default Description Parameter Default Description
endpoint with which
the SDK should PROFILE Connections in pool
communicate. use-idle-connection-
true should be closed
reaper
asynchronously.
profile- The name of the
Time to complete an default
api-call-timeout provider.profile-name pro le to use.
execution. Endpoint of the proxy
proxy.endpoint
server.
PROCESS
List of class
interceptors
interceptors. proxy.enabled false Enables HTTP proxy.
Command to execute
process-
to retrieve
Con guration parameters pre xed with quarkus.dynamodb.aws : provider.command
credentials. proxy.username Proxy username.
Parameter Default Description
process- proxy.password Proxy password.
Region that hosts Max bytes to retrieve
provider.process- 1024
region
DynamoDB. from process.
output-limit
For NTLM, domain
proxy.ntlm-domain
name.
Credentials that The amount of time
process-
should be used between credentials
provider.credential- PT15S
DEFAULT , STATIC , expire and proxy.ntlm- For NTLM,
refresh-threshold
SYSTEM_PROPERTY , credentials refreshed. workstation workstation name.
credentials.type DEFAULT
ENV_VARIABLE ,
PROFILE , CONTAINER ,
INSTANCE_PROFILE , process- proxy.preemptive-
Authenticate pre-
PROCESS , ANONYMOUS provider.async- Should fetch basic-authentication-
false emptively.
credential-update- credentials async. enabled
enabled
Credentials speci c parameters pre xed with
quarkus.dynamodb.aws.credentials : proxy.non-proxy- List of non proxy
In case of synchronous client, the next parameters can be hosts hosts.
Parameter Default Description con gured pre xed by quarkus.dynamodb.sync-client :

DEFAULT Parameter Default Description TLS manager: none ,


tls-managers-
system-property system-property ,
provider.type
connection- Connection file-store
10S
default- acquisition-timeout acquisation timeout.
provider.async- Should fetch
false
credential-update- credentials async. tls-managers-
enabled Max time to provider.file- Path to key store.
connection-max-idle-
60S connection to be store.path
time
opened.
default- Should reuse the last
provider.reuse-last- true successful tls-managers-
provider-enabled credentials. connection-timeout Connection timeout. provider.file- Key store type.
store.type

STATIC connection-time-to- Max time connection


0
live to be open. tls-managers-
provider.file- Key store password.
static- store.password
provider.access-key- AWS access key id. socket-timeout 30S Time to wait for data.
id
In case of asynchronous client, the next parameters can be
max-connections 50 Max connections. con gured pre xed by quarkus.dynamodb.async-client :
static-
AWS secret access
provider.secret- Parameter Default Description
key.
access-key Client send an HTTP
expect-continue-
true expect-continue connection- Connection
enabled 10S
handsake. acquisition-timeout acquisation timeout.
Parameter Default Description Parameter Default Description quarkus.s3.endpoint-override=http://localhost:8008
quarkus.s3.interceptors=io.quarkus.it.amazon.s3.S3ModifyRes
Max time to Sets the HTTP ponse
connection-max-idle- protocol HTTP_1_1
60S connection to be protocol. quarkus.s3.aws.region=us-east-1
time
opened. quarkus.s3.aws.credentials.type=static
quarkus.s3.aws.credentials.static-provider.access-key-id=te
Max number of st-key
max-http2-streams
connection-timeout Connection timeout. concurrent streams. quarkus.s3.aws.credentials.static-provider.secret-access-ke
y=test-secret

connection-time-to- Max time connection Enable custom event


0 event-loop.override false
live to be open. loop conf.
You can inject asynchronous client too:

Max number of event-loop.number-of- Number of threads to @Inject


max-concurrency 50 concurrent threads use in event loop. S3AsyncClient s3AsyncClient;
connections.

event-loop.thread- aws-java-sdk- Pre x of thread


Connections in pool name-prefix NettyEventLoop names. And you need to add the asynchronous Netty client:
use-idle-connection-
true should be closed
reaper
asynchronously. <dependency>
Amazon S3 <groupId>software.amazon.awssdk</groupId>
<artifactId>netty-nio-client</artifactId>
read-timeout 30S Read timeout. </dependency>
./mvnw quarkus:add-extension
-Dextensions="quarkus-amazon-s3"
write-timeout 30S Write timeout.
Con guration properties are the same as Amazon DynamoDB but
changing the pre x from dynamodb to s3 .
Endpoint of the proxy @Inject
proxy.endpoint
server. S3Client s3Client; Neo4j
Quarkus integrates with Neo4j:
proxy.enabled false Enables HTTP proxy. You need to set a HTTP client either URL Connection :
./mvnw quarkus:add-extension
<dependency> -Dextensions="quarkus-neo4j"
proxy.non-proxy- List of non proxy
hosts hosts. <groupId>software.amazon.awssdk</groupId>
<artifactId>url-connection-client</artifactId>
</dependency>
@Inject
TLS manager: none ,
org.neo4j.driver.Driver driver;
tls-managers-
system-property system-property ,
provider.type
file-store or Apache HTTP:
Con guration properties:
<dependency>
tls-managers-
provider.file- Path to key store.
<groupId>software.amazon.awssdk</groupId> quarkus.neo4j as pre x is skipped in the next table.
<artifactId>apache-client</artifactId>
store.path
</dependency> Pre x is quarkus.neo4j .

uri
tls-managers-
provider.file- Key store type. URI of Neo4j. (default: localhost:7687 )
quarkus.s3.sync-client.type=apache
store.type
authentication.username
Username. (default: neo4j )
tls-managers- And con gure it:
provider.file- Key store password. authentication.password
store.password
Password. (default: neo4j )

SSL Provider ( jdk , authentication.disabled


ssl-provider openssl , openssl- Disable authentication. (default: false )
refcnt ).
Enable metrics. (default: false )
@GET
quarkus.mongodb as pre x is skipped in the following table.
public Publisher<String> get() {
pool.log-leaked-sessions
return Multi.createFrom().resource(driver::rxSession,
Parameter Type Description
Enable leaked sessions logging. (default:`false`) session -> session.readTransaction(tx -> {
RxResult result = tx.run("MATCH (f:Fruit) RETUR
MongoDB connection
pool.max-connection-pool-size N f.name as name"); connection-string String
URI.
Max amount of connections. (default: 100 ) return Multi.createFrom().publisher(result.reco
rds())
.map(record -> record.get("name").asStr
pool.max-connection-lifetime Addresses passed as
ing()); hosts List<String>
Pooled connections older will be closed and removed from the host:port .
})
pool. (default: 1H )
).withFinalizer(session -> {
return Uni.createFrom().publisher(session.close()); application-name String Application name.
pool.connection-acquisition-timeout
});
Timout for connection adquisation. (default: 1M) }
Maximum number of
max-pool-size Int
pool.idle-time-before-connection-test connections.
Pooled connections idled in the pool for longer than this timeout
will be tested before they are used. (default: -1 )
MongoDB Client
Minimum number of
Quarkus integrates with MongoDB: min-pool-size Int
connections.
As Neo4j uses SSL communication by default, to create a native
executable you need to compile with next options GraalVM options:
./mvnw quarkus:add-extension
-H:EnableURLProtocols=http,https --enable-all-security-services - -Dextensions="quarkus-mongodb-client" max-connection-idle- Idle time of a pooled
Duration
H:+JNI time connection.

And Quarkus Maven Plugin with next con guration:


@Inject max-connection-life- Life time of pooled
Duration
com.mongodb.client.MongoClient client; time connection.
<artifactId>quarkus-maven-plugin</artifactId>
<executions>
@Inject
<execution>
io.quarkus.mongodb.reactive.ReactiveMongoClient client; Maximum wait time
<id>native-image</id> wait-queue-timeout Duration
for new connection.
<goals>
<goal>native-image</goal>
</goals> INFO: Reactive client uses exposes Mutiny API. Time period between
<configuration> maintenance-
Duration runs of maintenance
<enableHttpUrlHandler>true frequency
quarkus.mongodb.connection-string=mongodb://localhost:27018 job.
</enableHttpUrlHandler> quarkus.mongodb.write-concern.journal=false
<enableHttpsUrlHandler>true
</enableHttpsUrlHandler> Time to wait before
<enableAllSecurityServices>true maintenance-initial-
Multi MongoDB support Duration running the rst
</enableAllSecurityServices> delay
maintenance job.
<enableJni>true</enableJni>
You can con gure multiple MongoDB clients using same approach
</configuration>
as with DataSource . The syntax is quarkus.mongodb.<optional name>.
</execution>
<property> :
Multiplied with max-
</executions> pool-size gives max
wait-queue-multiple Int
numer of threads
quarkus.mongodb.users.connection-string = mongodb://mongo2:
waiting.
27017/userdb
Alternatively, and as a not recommended way in production, you quarkus.mongodb.inventory.connection-string = mongodb://mon
can disable SSL and Quarkus will disable Bolt SSL as well. go3:27017/invdb connection-timeout Duration
quarkus.ssl.native=false .

If you are using Neo4j 4.0, you can use fully reactive. Add the next
extension: quarkus-resteasy-mutiny . Inject the instance using socket-timeout Duration
@io.quarkus.mongodb.runtime.MongoClientName annotation:

tls-insecure boolean [false] Insecure TLS.


@Inject
@MongoClientName("users")
MongoClient mongoClient1; tls boolean [false] Enable TLS
Parameter Type Description Parameter Type Description person.persist();
person.update();
Implies hosts given Source of the person.delete();
replica-set-name String credentials.auth-
are a seed list. String authentication
source
credentials. List<Person> allPersons = Person.listAll();
person = Person.findById(personId);
server-selection- Time to wait for List<Person> livingPersons = Person.list("status", Status.A
Duration
timeout server selection. Authentication live);
credentials.auth-
Map<String, String> mechanism List<Person> persons = Person.list(Sort.by("name").and("bir
mechanism-properties
properties. th"));
Minimum ping time
local-threshold Duration to make a server
long updated = Person.update("name", "Mortal").where("statu
eligible. MongoDB Panache s", Status.Alive);

You can also use the Panache framework to write persistence part long countAll = Person.count();
Frequency to
when using MongoDB.
heartbeat-frequency Duration determine the state
Person.deleteById(id);
of servers.
./mvnw quarkus:add-extension Person.delete("status", Status.Alive);
-Dextensions="mongodb-panache"
primary ,
primaryPreferred , All list methods have equivalent stream versions.
read-preference secondary , Read preferences. MongoDB con guration comes from MongoDB Client section.
secondaryPreferred , Pagination
nearest
@MongoEntity(collection="ThePerson") You can also use pagination:
public class Person extends PanacheMongoEntity {
public String name;
Max number of PanacheQuery<Person> livingPersons =
concurrent Person.find("status", Status.Alive);
max-wait-queue-size Int @BsonProperty("birth")
operations allowed to livingPersons.page(Page.ofSize(25));
public LocalDate birthDate;
wait.
// get the first page
public Status status;
List<Person> firstPage = livingPersons.list();
Ensures are writes }
write-concern.safe boolean [true] // get the second page
are ack. List<Person> secondPage = livingPersons.nextPage().list();

Possible annotations in elds: @BsonId (for custom ID),


write- Journal writing @BsonProperty and @BsonIgnore .
concern.journal
boolean [true]
aspect. Range

@MongoEntity is optional. PanacheQuery<Person> livingPersons = Person


Value to all write .find("status", Status.Alive);
write-concern.w String
commands. List<Person> secondRange = livingPersons.range(25, 49).list
Multi-tenancy with MongoDB Panache
();

write-concern.retry- Retry writes if @MongoEntity(collection = "TheBook", clientName = "client2"


boolean [false]
writes network fails. , database = "database2")
You cannot mix pagination and range.

write-concern.w- Timeout to all write Queries


Duration Methods provided are similar of the ones shown in Persistence
timeout commands. section. Native MongoDB queries are supported (if they start with { or
org.bson.Document instance) as well as Panache Queries. Panache
Queries equivalence in MongoDB:
credentials.username String Username.
firstname = ?1 and status = ?2 → {'firstname': ?1, 'status': ?
2}
credentials.password String Password.
amount > ?1 and firstname != ?2 → {'amount': {'$gt': ?1},
'firstname': {'$ne': ?2}}
credentials.auth- MONGO-CR , GSSAPI ,
mechanism PLAIN , MONGODB-X509
lastname like ?1 → {'lastname': {'$regex': ?1}}

lastname is not null → {'lastname':{'$exists': true}}


PanacheQL refers to the Object parameter name but native Then you can de ne interfaces for de ning endpoints:
<plugin>
queries refer to MongoDB eld names. <groupId>org.jboss.jandex</groupId>
In case of Active Record pattern:
<artifactId>jandex-maven-plugin</artifactId>
Projection <version>1.0.3</version>
<executions> public interface DeveloperResource extends PanacheMongoEnti
Projection can be done for both PanacheQL and native queries. <execution> tyResource<Developer, Long> {
<id>make-index</id> }

import io.quarkus.mongodb.panache.ProjectionFor; <goals>


<goal>jandex</goal>
@ProjectionFor(Person.class) (1) </goals> In case of Repository:
public class PersonName { </execution>
public String name; </executions>
public interface DeveloperResource extends PanacheMongoRepo
} <dependencies>
sitoryResource<DeveloperRepository, Developer, Long> {
<dependency>
}
PanacheQuery<PersonName> shortQuery = Person.find("status " <groupId>org.jboss</groupId>
, Status.Alive).project(PersonName.class); <artifactId>jandex</artifactId>
<version>2.1.1.Final</version>
</dependency> Cassandra
</dependencies>
1 Entity class. </plugin> Quarkus integrates with Cassandra and DataStax Object Mapper.
Testing
<dependency>
To mock using active record pattern: Panache includes an annotation processor that enhance your <groupId>com.datastax.oss.quarkus</groupId>
entities. If you disable annotation processors you might need to <artifactId>cassandra-quarkus-client</artifactId>
<dependency> create a marker le on Panache archives at META-INF/panache- </dependency>
archive.marker manually.
<groupId>io.quarkus</groupId>
<artifactId>quarkus-panache-mock</artifactId>
Reactive Panache
<scope>test</scope> Enities and DAOs are generated as you have been doing with
</dependency>
MongoDB with Panache allows using reactive implementation too DataStax Object Mapper.
by using ReactivePanacheMongoEntity or
ReactivePanacheMongoEntityBase or ReactivePanacheMongoRepository
You need to create a DaoProducer:
or ReactivePanacheMongoRepositoryBase depending on your style.
@Test
@Inject
public void testPanacheMocking() {
public FruitDaoProducer(QuarkusCqlSession session) {
PanacheMock.mock(Person.class); public class ReactivePerson extends ReactivePanacheMongoEnt
FruitMapper mapper = new FruitMapperBuilder(session).buil
ity {
d();
Mockito.when(Person.count()).thenReturn(23l); public String name;
fruitDao = mapper.fruitDao();
Assertions.assertEquals(23, Person.count()); }
}
PanacheMock.verify(Person.class, Mockito.times(1)).coun
t(); CompletionStage<Void> cs1 = person.persist();
@Produces
} CompletionStage<List<ReactivePerson>> allPersons = Reactive
@ApplicationScoped
Person.listAll();
FruitDao produceFruitDao() {
Publisher<ReactivePerson> allPersons = ReactivePerson.strea
return fruitDao;
mAll();
DAO pattern }

Uni<List<PersonName>> persons = ReactivePersonEntity.find(


@ApplicationScoped "lastname", name).project(PersonName.class).list();
public class PersonRepository Cassandra con guration:
implements PanacheMongoRepository<Person> {
}
MongoDB REST Data Panache quarkus.cassandra.contact-points=127.0.0.1:9042
quarkus.cassandra.local-datacenter=datacenter1
quarkus.cassandra.keyspace=k1
MongoDB REST Data with Panache extension can generate the
Jandex quarkus.cassandra.auth.username=john
basic CRUD endpoints for your entities and repositories.
quarkus.cassandra.auth.password=s3cr3t
If entities are de ned in external JAR, you need to enable in these
projects the Jandex plugin in project. ./mvnw quarkus:add-extension
-Dextensions="mongodb-rest-data-panache"
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.
You also need to add the JDBC driver extension and a JSON
Marshaller (ie resteasy-jackson ). If MicroPro le Metrics extension is registered, the Cassandra
extension can provide (if enabled) metrics about the session:
quarkus.cassandra.metrics.enabled=true Reactive Programming @GET
quarkus.cassandra.metrics.session-enabled=connected-nodes,b @Produces(MediaType.TEXT_PLAIN)
ytes-sent Quarkus implements MicroPro le Reactive spec and uses RXJava2 public Uni<String> hello() {
quarkus.cassandra.metrics.node-enabled=pool.open-connection to provide reactive programming model. return Uni.createFrom().item(() -> "hello");
s }
./mvnw quarkus:add-extension
-Dextensions="quarkus-smallrye-reactive-streams-operator @GET
@Produces(MediaType.TEXT_PLAIN)
Reactive s"
public Multi<String> multi() {
You can also use Mutiny to de ne a reactive DAO: return Multi.createFrom().items("hello", "world");
}
Asynchronous HTTP endpoint is implemented by returning Java
@Dao CompletionStage . You can create this class either manually or using
public interface FruitDaoReactive { MicroPro le Reactive Streams spec:
Mutiny
@Update
@GET
Uni<Void> update(Fruit fruit); Quarkus integrates with Mutiny as reactive programming library:
@Path("/reactive")
@Produces(MediaType.TEXT_PLAIN)
@Select ./mvnw quarkus:add-extension
public CompletionStage<String> getHello() {
MutinyMappedReactiveResultSet<Fruit> findById(String stor -Dextensions="mutiny"
return ReactiveStreams.of("h", "e", "l", "l", "o")
eId);
.map(String::toUpperCase)
}
.toList()
.run()
@Mapper @ApplicationScoped
.thenApply(list -> list.toString());
public interface FruitMapper { public static class ReactiveHello {
}

@DaoFactory public Uni<String> greeting() {


FruitDaoReactive fruitDaoReactive(); return Uni.createFrom().item(() -> "hello")
} Creating streams is also easy, you just need to return Publisher .emitOn(Infrastructure.getDefaultExecutor
object. ());
}
@GET
@Path("/stream") public Multi<String> stream() {
@Produces(MediaType.SERVER_SENT_EVENTS) return Multi.createFrom().items("hello", "world")
public Publisher<String> publishers() { .emitOn(Infrastructure.getDefaultExecutor
return Flowable ());
.interval(500, TimeUnit.MILLISECONDS) }
.map(s -> atomicInteger.getAndIncrement()) }
.map(i -> Integer.toString(i));
}
Converting from/to RxJava2 or Reactor APIs:

Mutiny and JAX-RS RxJava 2

Apart from the CompletionStage support, there is also support for <dependency>
Mutiny. <groupId>io.smallrye.reactive</groupId>
<artifactId>mutiny-rxjava</artifactId>
./mvnw quarkus:add-extension </dependency>
-Dextensions="quarkus-resteasy-mutiny"

From RxJava2 :
Uni<Void> uniFromCompletable = Uni.createFrom() Uni<String> uniFromMono = Uni.createFrom().converter(UniRea package org.acme.rest;
.converter(UniRxConvert ctorConverters.fromMono(), mono); import javax.ws.rs.GET;
ers.fromCompletable(), completable); Uni<String> uniFromFlux = Uni.createFrom().converter(UniRea import javax.ws.rs.Path;
Uni<String> uniFromSingle = Uni.createFrom() ctorConverters.fromFlux(), flux); @Path("rest")
.converter(UniRxConverters. Multi<String> multiFromMono = Multi.createFrom().converter public class Endpoint {
fromSingle(), single); (MultiReactorConverters.fromMono(), mono);
Uni<String> uniFromObservable = Uni.createFrom() Multi<String> multiFromFlux = Multi.createFrom().converter @Path("hello")
.converter(UniRxConverters. (MultiReactorConverters.fromFlux(), flux); @GET
fromObservable(), observable); public String hello(){
Uni<String> uniFromFlowable = Uni.createFrom() // executed in event-loop
.converter(UniRxConverters. return "Hello, World!";
To Reactor :
fromFlowable(), flowable); }
...
Mono<String> mono = uni.convert().with(UniReactorConverter @GET
Multi<Void> multiFromCompletable = Multi.createFrom() s.toMono()); public Uni<Book> culinaryGuide(){
.converter(MultiRxC Flux<String> flux = uni.convert().with(UniReactorConverter // executed in event-loop but not blocking
onverters.fromCompletable(), completable); s.toFlux()); return Book.findByIsbn("978-2081229297");
Multi<String> multiFromObservable = Multi.createFrom() }
.converter(MultiRxC Mono<String> mono2 = multi.convert().with(MultiReactorConve
onverters.fromObservable(), observable); rters.toMono()); @io.smallrye.common.annotation.Blocking
Multi<String> multiFromFlowable = Multi.createFrom() Flux<String> flux2 = multi.convert().with(MultiReactorConve @GET
.converter(MultiRxC rters.toFlux()); public String blockingHello() throws InterruptedExcepti
onverters.fromFlowable(), flowable); on {
... // executed in worker-thread
CompletionStages or Publisher return "Yaaaawwwwnnnnnn…";
}

To RxJava2 : CompletableFuture<String> future = Uni


}
.createFrom().completionStage(CompletableFuture.sup
Completable completable = uni.convert().with(UniRxConverter plyAsync(() -> "hello"));
s.toCompletable());
Single<Optional<String>> single = uni.convert().with(UniRxC CompletationStage<String> cs = Uni Reactive Messaging
onverters.toSingle()); .createFrom().subscribeAsCompletionStage();
Observable<String> observable = uni.convert().with(UniRxCon Quarkus relies on MicroPro le Reactive Messaging spec to
verters.toObservable()); implement reactive messaging streams.
Flowable<String> flowable = uni.convert().with(UniRxConvert Multi implements Publisher .
ers.toFlowable());
mvn quarkus:add-extension
... RESTEasy Reactive -Dextensions="
io.quarkus:quarkus-smallrye-reactive-messaging"
Completable completable = multi.convert().with(MultiRxConve
RESTEasy Reactive is a new implementation of JAX-RS but fully
rters.toCompletable());
reactive.
Single<Optional<String>> single = multi.convert().with(Mult
iRxConverters.toSingle()); You can just start using in-memory streams by using @Incoming to
Observable<String> observable = multi.convert().with(MultiR mvn quarkus:add-extension produce data and @Outgoing to consume data.
xConverters.toObservable()); -Dextensions="quarkus-resteasy-reactive"
Flowable<String> flowable = multi.convert().with(MultiRxCon Produce every 5 seconds one piece of data.
verters.toFlowable());
... @ApplicationScoped
public class ProducerData {

@Outgoing("my-in-memory")
Reactor API
public Flowable<Integer> generate() {
return Flowable.interval(5, TimeUnit.SECONDS)
<dependency> .map(tick -> random.nextInt(100));
<groupId>io.smallrye.reactive</groupId> }
<artifactId>mutiny-reactor</artifactId> }
</dependency>

or in Mutiny:
From Reactor :
@ApplicationScoped @Inject @Stream(“out”) mp.messaging.outgoing.generated-price.connector=
public class ProducerData { Publisher<String> result; smallrye-kafka
@Outgoing("my-in-memory") mp.messaging.outgoing.generated-price.topic=
public Multi<Integer> generate() { @GET prices
return Multi.createFrom().ticks().every(Duration.of @Produces(SERVER_SENT_EVENTS) mp.messaging.outgoing.generated-price.bootstrap.servers=
Seconds(5)) public Publisher<String> stream() { localhost:9092
.onItem().apply(n -> random.nextInt(100)); return result; mp.messaging.outgoing.generated-price.value.serializer=
} } org.apache.kafka.common.serialization.IntegerSerializer
}
mp.messaging.incoming.prices.connector=
smallrye-kafka
Message → Business Logic
mp.messaging.incoming.prices.value.deserializer=
If you want to dispatch to all subscribers you can annotate the
org.apache.kafka.common.serialization.IntegerDeserializ
method with @Broadcast . @ApplicationScoped er
public class ReceiverMessages {
Consumes generated data from my-in-memory stream.
@Incoming("prices")
public void print(String price) {
@ApplicationScoped } A complete list of supported properties are in Kafka site. For the
public class ConsumerData { } producer and for consumer
@Incoming("my-in-memory")
public void randomNumber(int randomNumber) { JSON-B Serializer/Deserializer
System.out.println("Received " + randomNumber);
}
To indicate that the method should be executed on a worker pool You can use JSON-B to serialize/deserialize objects.
}
you can use @Blocking :
./mvnw quarkus:add-extension
@Outgoing("Y") -Dextensions="quarkus-kafka-client"
@Incoming("X")
You can also inject an stream as a eld:
@Blocking

To serialize you can use


@Inject
io.quarkus.kafka.client.serialization.JsonbSerializer .
@Stream("my-in-memory") Publisher<Integer> randomRumbers;
To customize:
To deserialize you need to extend
io.quarkus.kafka.client.serialization.JsonbDeserializer and
@Blocking(value="my-custom-pool", ordered = false)
@Inject @Stream("generated-price")
provide a type.
Emitter<String> emitter;
public class BeerDeserializer
smallrye.messaging.worker.my-custom-pool.max-concurrency=3 extends JsonbDeserializer<Beer> {

Patterns
public BeerDeserializer() {
super(Beer.class);
REST API → Message Possible implementations are:
}
In-Memory
@Inject @Stream(“in”) }
Emitter<String> emitter;
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
emitter.send(message);
eld. AMQP
Kafka To integrate with AMQP you need to add next extensions:
Message → Message
To integrate with Kafka you need to add next extensions:
./mvnw quarkus:add-extension
@Incoming(“in”) -Dextensions="reactive-messaging-amqp"
@Outgoing(“out”) mvn quarkus:add-extension
public String process(String in) { -Dextensions="
} io.quarkus:quarkus-smallrye-reactive-messaging-kafka"
Then @Outgoing , @Incoming or @Stream can be used.

AMQP con guration schema: mp.messaging.[outgoing|incoming].


Message → SSE Then @Outgoing , @Incoming or @Stream can be used. {stream-name}.<property>=<value> . Special properties amqp-username
and amqp-password are used to con gure AMQP broker credentials.
Kafka con guration schema: mp.messaging.[outgoing|incoming].
{stream-name}.<property>=<value> . The connector type is smallrye-amqp .

The connector type is smallrye-kafka .


amqp-username=quarkus Kafka Streams Common Reeactive DataSource Client con guration properties
pre xed with quarkus.datasource :
amqp-password=quarkus
# write Create streaming queries with the Kafka Streams API.
reactive.cache-prepared-statements
mp.messaging.outgoing.generated-price.connector=
smallrye-amqp Prepared statements should be cached on the client side.
./mvnw quarkus:add-extension
mp.messaging.outgoing.generated-price.address= (default: false )
-Dextensions="kafka-streams"
prices
mp.messaging.outgoing.generated-price.durable= reactive.url
true The datasource URL.
# read
All we need to do for that is to declare a CDI producer method
mp.messaging.incoming.prices.connector=
which returns the Kafka Streams
reactive.max-size
org.apache.kafka.streams.Topology :
smallrye-amqp
The datasource pool maximum size.
mp.messaging.incoming.prices.durable=
true @ApplicationScoped
reactive.trust-all
public class TopologyProducer {
@Produces All server certi cates should be trusted. (default: false )
public Topology buildTopology() {
A complete list of supported properties for AMQP. reactive.trust-certificate-pem
org.apache.kafka.streams.StreamsBuilder.StreamsBuil

MQTT der Trust con guration in the PEM format.


builder = new StreamsBuilder();
To integrate with MQTT you need to add next extensions: // ... reactive.trust-certificate-jks
builder.stream()
Trust con guration in the JKS format.
.join()
./mvnw quarkus:add-extension
// ...
-Dextensions="vertx, smallrye-reactive-streams-operator reactive.trust-certificate-pfx
.toStream()
s Trust con guration in the PFX format.
.to();
smallrye-reactive-messaging"
return builder.build();
} reactive.key-certificate-pem
} Key/cert con guration in the PEM format.
And add io.smallrye.reactive:smallrye-reactive-messaging-mqtt-
1.0:0.0.10 dependency in your build tool. reactive.key-certificate-jks

Then @Outgoing , @Incoming or @Stream can be used. Previous example produces content to another stream. If you want Key/cert con guration in the JKS format.
to write interactive queries, you can use Kafka streams.
MQTT con guration schema: mp.messaging.[outgoing|incoming]. reactive.key-certificate-pfx
{stream-name}.<property>=<value> . @Inject Key/cert con guration in the PFX format.
KafkaStreams streams;
The connector type is smallrye-mqtt .
reactive.thread-local
return streams
Use one connection pool per thread.
mp.messaging.outgoing.topic-price.type= .store("stream", QueryableStoreTypes.keyValueStore
smallrye-mqtt ());
reactive.reconnect-attempts
mp.messaging.outgoing.topic-price.topic=
prices The number of reconnection attempts when a pooled connection
mp.messaging.outgoing.topic-price.host= cannot be established on rst try. (default: 0 )
The Kafka Streams extension is con gured via the Quarkus
localhost
con guration le application.properties .
mp.messaging.outgoing.topic-price.port= reactive.reconnect-interval
1883 The interval between reconnection attempts when a pooled
quarkus.kafka-streams.bootstrap-servers=localhost:9092
mp.messaging.outgoing.topic-price.auto-generated-client-id= connection cannot be established on rst try. (default: PT1S )
quarkus.kafka-streams.application-id=temperature-aggregator
true
quarkus.kafka-streams.application-server=${hostname}:8080
reactive.idle-timeout
quarkus.kafka-streams.topics=weather-stations,temperature-v
mp.messaging.incoming.prices.type=
alues The maximum time without data written to or read from a
smallrye-mqtt
connection before it is removed from the pool.
mp.messaging.incoming.prices.topic=
kafka-streams.cache.max.bytes.buffering=10240
prices
mp.messaging.incoming.prices.host=
kafka-streams.commit.interval.ms=1000 Reactive PostgreSQL Client
localhost
mp.messaging.incoming.prices.port= You can use Reactive PostgreSQL to execute queries to PostreSQL
1883 IMPORTANT: All the properties within the kafka-streams database in a reactive way, instead of using JDBC way.
mp.messaging.incoming.prices.auto-generated-client-id= namespace are passed through as-is to the Kafka Streams engine.
true Changing their values requires a rebuild of the application. ./mvnw quarkus:add-extension
-Dextensions="quarkus-reactive-pg-client"
Reactive DataSource Properties
Database con guration is the same as shown in Persistence Reactive Transactions Artemis JMS
section, but URL is different as it is not a jdbc.
If you want to use JMS with Artemis, you can do it by using its
io.vertx.mutiny.sqlclient.SqlClientHelper is an util class that
extension:
quarkus.datasource.db-kind=postgresql allows you to run reactive persisten code within a transaction.
quarkus.datasource.reactive.url=postgresql:///your_database
./mvnw quarkus:add-extension
Uni<Void> r = SqlClientHelper.inTransactionUni(client, tx -
-Dextensions="quarkus-artemis-jms"
> {
Then you can inject io.vertx.mutiny.pgclient.PgPool class. Uni<RowSet<Row>> insertOne = tx.preparedQuery("INSE
RT INTO fruits (name) VALUES ($1) RETURNING (id)")
@Inject .execute(Tuple.of(fruit1.name)); And then you can inject javax.jms.ConnectionFactory :

PgPool client; });


@ApplicationScoped
Uni<List<Fruit>> fruits = public class ArtemisConsumerManager {
client.preparedQuery("SELECT * FROM fruits")
ActiveMQ Artemis @Inject
.onItem().apply(rowSet -> {
JsonArray jsonArray = new JsonArray(); ConnectionFactory connectionFactory;
Quarkus uses Reactive Messaging to integrate with messaging
for (Row row : rowSet) {
systems, but in case you need deeper control when using Apache private Connection connection;
jsonArray.add(from(row));
ActiveMQ Artemis there is also an extension:
}
return jsonArray; @PostConstruct
}) ./mvnw quarkus:add-extension public void init() throws JMSException {
-Dextensions="quarkus-artemis-core" connection = connectionFactory.createConnection();
connection.start();
}
Reactive MySQL Client And then you can inject }
org.apache.activemq.artemis.api.core.client.ServerLocator
You can use Reactive MySQL to execute queries to MySQL instance.
database in a reactive way, instead of using JDBC.
Con guration options are the same as Artemis core.
@ApplicationScoped
./mvnw quarkus:add-extension
public class ArtemisConsumerManager {
-Dextensions="quarkus-reactive-mysql-client"
Vert.X Reactive Clients
@Inject
ServerLocator serverLocator; Vert.X Reactive clients in Quarkus, the next clients are supported
Database con guration is the same as shown in Persistence and you need to add the dependency to use them:
section, but URL is different as it is not a jdbc. private ClientSessionFactory connection;
Vert.X Mail Client
quarkus.datasource.db-kind=mysql @PostConstruct
io.smallrye.reactive:smallrye-mutiny-vertx-mail-client
quarkus.datasource.reactive.url=mysql:///your_database public void init() throws Exception {
connection = serverLocator.createSessionFactory();
Vert.X MongoDB Client
}
} io.smallrye.reactive:smallrye-mutiny-vertx-mongo-client
Then you can inject io.vertx.mutiny.mysqlclient.MySQLPool class.
Vert.X Redis Client
Reactive DB2 Client And con gure ServerLocator in application.properties :
io.smallrye.reactive:smallrye-mutiny-vertx-redis-client

You can use Reactive DB2 to execute queries to DB2 database in a Vert.X Cassandra Client
reactive way, instead of using JDBC. quarkus.artemis.url=tcp://localhost:61616
io.smallrye.reactive:smallrye-mutiny-vertx-cassandra-client

./mvnw quarkus:add-extension Vert.X Consul Client


-Dextensions="quarkus-reactive-db2-client" You can con gure ActiveMQ Artemis in application.properties le
io.smallrye.reactive:smallrye-mutiny-vertx-consul-client
by using next properties pre xed with quarkus :

artemis.url Vert.X Kafka Client


Database con guration is the same as shown in Persistence
Connection URL. io.smallrye.reactive:smallrye-mutiny-vertx-kafka-client
section, but URL is different as it is not a jdbc.
artemis.username Vert.X AMQP Client
quarkus.datasource.db-kind=db2
quarkus.datasource.reactive.url=vertx-reactive:db2://localh
Username for authentication. io.smallrye.reactive:smallrye-mutiny-vertx-amqp-client

ost:50005/hreact
artemis.password Vert.X RabbitMQ Client
Password for authentication. io.smallrye.reactive:smallrye-mutiny-vertx-rabbitmq-client

Then you can inject i i db2 li 2 l class


Example of Vert.X Web Client:
quarkus.sqs.sync-client.type=apache TLS
@Inject You can trust all certi cates globally by using quarkus.tls.trust-
Vertx vertx; all=true
You can go async by using Mutiny:
private WebClient client;
@Inject
RBAC
@PostConstruct software.amazon.awssdk.services.sqs.SqsAsyncClient sqs;
You can set RBAC using annotations or in application.properties .
void initialize() {
this.client = WebClient.create(vertx, ...); Uni.createFrom()
Annotations
} .completionStage(
sqs.sendMessage(m -> m.queueUrl(queueUrl).messageBo You can de ne roles by using
dy(message)) javax.annotation.security.RolesAllowed annotation.
)
Amazon SQS Client .onItem()...
@RolesAllowed("Subscriber")

return Uni.createFrom()
./mvnw quarkus:add-extension
.completionStage(
-Dextensions="amazon-sqs"
sqs.receiveMessage(m -> m.maxNumberOfMessages(10).q You can use io.quarkus.security.Authenticated as a shortcut of
ueueUrl(queueUrl)) @RolesAllowed("*") .
)
Injecting the client: .onItem() To alter RBAC behaviour there are two con guration properties:

@Inject quarkus.security.deny-unannotated=true
software.amazon.awssdk.services.sqs.SqsClient sqs; And you need to add the asynchronous Netty client:
SendMessageResponse response = sqs.sendMessage(m -> m.queue
<dependency> Con guration options:
Url(queueUrl).messageBody(message));
<groupId>software.amazon.awssdk</groupId>
quarkus.jaxrs.deny-uncovered
<artifactId>netty-nio-client</artifactId>
List<Message> messages = sqs.receiveMessage(m -> m.maxNumbe
</dependency> If true denies by default to all JAX-RS endpoints. (default: false )
rOfMessages(10).queueUrl(queueUrl)).messages();

quarkus.security.deny-unannotated

Con guration properties are the same as Amazon DynamoDB but If true denies by default all CDI methods and JAX-RS endpoints.
And con gure it:
changing the pre x from dynamodb to sqs . (default: false )

quarkus.sqs.endpoint-override=http://localhost:8010 By default in Quarkus, if an incoming request has a credential the


quarkus.sqs.aws.region=us-east-1 request will always be authenticated (even if the target page does
quarkus.sqs.aws.credentials.type=static not require authentication).
quarkus.sqs.aws.credentials.static-provider.access-key-id=t
est-key You can change this behaviour by setting
quarkus.sqs.aws.credentials.static-provider.secret-access-k quarkus.http.auth.proactive property to false .
ey=test-secret
File Con guration

De ning RBAC in application.properties instead of using


You need to set a HTTP client either URL Connection :
annotations.

<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.http.auth.policy.role-policy1.roles-allowed= quarkus.security.security-providers=BC
Sets header such as Cookie is used to pass the token. (default:
Authorization ).
user,admin quarkus.security.security-providers=BCJSSE
quarkus.http.auth.permission.roles1.paths= quarkus.security.security-providers=BCFIPS
smallrye.jwt.token.cookie
/roles-secured/*,/other/*,/api/* quarkus.security.security-providers=BCFIPSJSSE
quarkus.http.auth.permission.roles1.policy= Name of the cookie containing a token.
role-policy1
smallrye.jwt.token.schemes
quarkus.http.auth.permission.permit1.paths= JWT Comma-separated list containing an alternative single or multiple
/public/* schemes. (default: Bearer ).
quarkus.http.auth.permission.permit1.policy= Quarkus implements MicroPro le JWT RBAC spec.
permit smallrye.jwt.require.named-principal
quarkus.http.auth.permission.permit1.methods= mvn quarkus:add-extension
A token must have a upn or preferred_username or sub claim set
GET -Dextensions="io.quarkus:quarkus-smallrye-jwt"
if using java.security.Principal . True makes throw an exception
if not set. (default: false ).
quarkus.http.auth.permission.deny1.paths=
/forbidden
Minimum JWT required claims: typ , alg , kid , iss , sub , exp , iat , smallrye.jwt.path.sub
quarkus.http.auth.permission.deny1.policy=
jti , upn , groups .
deny Path to the claim with subject name.
You can inject token by using JsonWebToken or a claim individually by
smallrye.jwt.claims.sub
using @Claim .
You need to provide permissions set by using the roles-allowed Default sub claim value.
property or use the built-in ones deny , permit or authenticated . @Inject
JsonWebToken jwt; smallrye.jwt.path.groups
You can use enabled property (ie Path to the claim containing the groups.
quarkus.http.auth.permission.permit1.enabled ) to enable the entire
@Inject
permission set. @Claim(standard = Claims.preferred_username) smallrye.jwt.groups-separator
String name; Separator for splitting a string which may contain multiple group
Testing
values. (default. ` `).
@Inject
Quarkus provides explicit support for testing with different users,
@Claim("groups")
and with the security subsystem disabled. smallrye.jwt.claims.groups
Set<String> groups;
Default groups claim value.
<dependency>
@Inject
<groupId>io.quarkus</groupId> smallrye.jwt.jwks.refresh-interval
JWTParser parser;
<artifactId>quarkus-test-security</artifactId>
JWK cache refresh interval in minutes. (default: 60 ).
<scope>test</scope>
</dependency>
smallrye.jwt.expiration.grace
Set of supported types: String , Set<String> , Long , Boolean,
`javax.json.JsonValue , Optional , Expiration grace in seconds. (default: 60 ).
org.eclipse.microprofile.jwt.ClaimValue .
@Test smallrye.jwt.verify.aud
@TestSecurity(authorizationEnabled = false) And con guration in src/main/resources/application.properties :
Comma separated list of the audiences that a token aud claim
void someTestMethod() { may contain.
... mp.jwt.verify.publickey.location=
} META-INF/resources/publicKey.pem smallrye.jwt.verify.algorithm
mp.jwt.verify.issuer=
@Test
Signature algorith. (defsult: RS256 )
https://quarkus.io/using-jwt-rbac
@TestSecurity(user = "testUser", roles = {"admin", "user"})
smallrye.jwt.token.kid
void someTestMethod() {
... If set then the veri cation JWK key as well every JWT token must
Con guration options:
} have a matching kid header.
mp.jwt.verify.publickey
smallrye.jwt.time-to-live
Public Key text itself to be supplied as a string.
The maximum number of seconds that a JWT may be issued for
BouncyCastle use.
mp.jwt.verify.publickey.location Relative path or URL of a public
Quarkus supports BouncyCastle, you only need to add the key.
smallrye.jwt.sign.key-location
BouncyCastle dependency and con gure the security provider:
mp.jwt.verify.issuer Location of a private key which will be used to sign the claims
iss accepted as valid. when either a no-argument sign() or innerSign() method is
called.
smallrye.jwt.token.header
smallrye.jwt.encrypt.key-location
Location of a public key which will be used to encrypt the claims tenant-enabled
Jwt.claims()
or inner JWT when a no-argument encrypt() method is called. If the tenant con guration is enabled. (default: true )
.issuer("https://server.com")
.claim("customClaim", 3)
Supported public key formats: .sign(createKey()); application-type

PKCS#8 PEM The application type. Possible values: web_app , service . (default:
JwtSignatureBuilder jwtSignatureBuilder = Jwt.claims("/test service )
JsonToken.json").jws();
JWK
jwtSignatureBuilder connection-delay
JWKS .signatureKeyId("some-key-id")
The maximum amount of time the adapter will try connecting.
.signatureAlgorithm(SignatureAlgorithm.ES256)
JWK Base64 URL .header("custom-header", "custom-value");
auth-server-url
.sign(createKey());
JWKS Base64 URL The base URL of the OpenID Connect (OIDC) server.
Jwt.claims("/testJsonToken.json")
To send a token to server-side you should use Authorization .encrypt(createKey()); introspection-path
header: curl -H "Authorization: Bearer eyJraWQiOi…" . Relative path of the RFC7662 introspection service.
JwtEncryptionBuilder jwtEncryptionBuilder = Jwt.claims("/te
To inject claim values, the bean must be @RequestScoped CDI stJsonToken.json").jwe(); jwks-path
scoped. If you need to inject claim values in scope with a lifetime jwtEncryptionBuilder
greater than @RequestScoped then you need to use Relative path of the OIDC service returning a JWK set.
.keyEncryptionKeyId("some-key-id")
javax.enterprise.inject.Instance interface.
.keyEncryptionAlgorithm(KeyEncryptionAlgorithm.ECDH_E
public-key
S_A256KW)
@Inject .header("custom-header", "custom-value"); Public key for the local JWT token veri cation
@Claim(standard = Claims.iat) .encrypt(createKey());
private Instance<Long> providerIAT; client-id
Jwt.claims("/testJsonToken.json") The client-id of the application.
.innerSign(createKey());
RBAC .encrypt(createKey()); roles.role-claim-path
Path to the claim containing an array of groups. ( realm/groups )
JWT groups claim is directly mapped to roles to be used in security
annotations.
OpenId Connect roles.role-claim-separator

Separator for splitting a string which may contain multiple group


@RolesAllowed("Subscriber") Quarkus can use OpenId Connect or OAuth 2.0 authorization values.
servers such as Keycloak to protect resources using bearer token
issued by Keycloak server. token.issuer
Generate tokens Issuer claim value.
mvn quarkus:add-extension
JWT generation API: -Dextensions="using-openid-connect" token.audience

Audience claim value.

You can also protect resources with security annotations. token.expiration-grace


Expiration grace period in seconds.
@GET
@RolesAllowed("admin") token.principal-claim
Name of the claim which contains a principal name.

Con gure application to Keycloak service in application.properties token.refresh-expired


le. If property is enabled then a refresh token request is performed.

quarkus.oidc.realm=quarkus credentials.secret
quarkus.oidc.auth-server-url=http://localhost:8180/auth
The client secret
quarkus.oidc.resource=backend-service
quarkus.oidc.bearer-only=true
authentication.redirect-path
quarkus.oidc.credentials.secret=secret
Relative path for calculating a redirect_uri query parameter.

authentication.restore-path-after-redirect
Con guration options with quarkus.oidc pre x:
The original request URI used before the authentication will be
enabled restored after the user has been redirected back to the
The OIDC is enabled. (default: true )
application. (default: true )
authentication.scopes
quarkus.oidc.auth-server-url=http://localhost:8180/auth/rea Authenticating via HTTP
List of scopes. lms/quarkus
quarkus.oidc.client-id=multi-tenant-client HTTP basic auth is enabled by the quarkus.http.auth.basic=true
authentication.extra-params quarkus.oidc.application-type=web-app property.
Additional properties which will be added as the query
parameters . quarkus.oidc.tenant-b.auth-server-url=https://accounts.goog HTTP form auth is enabled by the
le.com quarkus.http.auth.form.enabled=true property.
authentication.cookie-path quarkus.oidc.tenant-b.application-type=web-app
quarkus.oidc.tenant-b.client-id=xxxx Then you need to add elytron-security-properties-file or elytron-
Cookie path parameter. security-jdbc .
quarkus.oidc.tenant-b.credentials.secret=yyyy
quarkus.oidc.tenant-b.token.issuer=https://accounts.google.
proxy.host
com Security with Properties File
The host (name or IP address) of the Proxy. quarkus.oidc.tenant-b.authentication.scopes=email,profile,o
penid You can also protect endpoints and store identities (user, roles) in
proxy.port the le system.
The port number of the Proxy. (default: 80 )

proxy.username
OAuth2 mvn quarkus:add-extension
-Dextensions="elytron-security-properties-file"
The username to authenticate. Quarkus integrates with OAuth2 to be used in case of opaque
tokens (none JWT) and its validation against an introspection
proxy.password endpoint. You need to con gure the extension with users and roles les:
The password to authenticate.
And con guration in src/main/resources/application.properties :
mvn quarkus:add-extension
end-session-path -Dextensions="security-oauth2"
quarkus.security.users.file.enabled=true
Relative path of the OIDC end_session_endpoint .
quarkus.security.users.file.users=test-users.properties
quarkus.security.users.file.roles=test-roles.properties
logout.path And con guration in src/main/resources/application.properties : quarkus.security.users.file.auth-mechanism=BASIC
The relative path of the logout endpoint at the application. quarkus.security.users.file.realm-name=MyRealm
quarkus.oauth2.client-id=client_id quarkus.security.users.file.plain-text=true
logout.post-logout-path quarkus.oauth2.client-secret=secret
Relative path of the application endpoint where the user should quarkus.oauth2.introspection-url=http://oauth-server/intros
be redirected to after logging out. pect
Then users.properties and roles.properties :

tls.verification
scott=jb0ss
Sets the TLs veri cation. Possible values: REQUIRED , NONE . And you can map roles to be used in security annotations. jdoe=p4ssw0rd
(default: REQUIRED ).
@RolesAllowed("Subscriber")
With Keycloak OIDC server
https://host:port/auth/realms/{realm} where {realm} has scott=Admin,admin,Tester,user
to be replaced by the name of the Keycloak realm. jdoe=NoRolesUser
Con guration options:
You can use quarkus.http.cors property to enable
consuming form different domain. quarkus.oauth2.enabled

Determine if the OAuth2 extension is enabled. (default: true ) IMPORTANT: If plain-text is set to false (or omitted) then
Multi-tenancy passwords must be stored in the form MD5
quarkus.oauth2.client-id
( username :`realm`:`password`).
Multi-tenancy is supported by adding a sub-category to OIDC
con guration properties (ie quarkus.oidc.{tenent_id}.property ). The OAuth2 client id used to validate the token. Elytron File Properties con guration properties. Pre x
quarkus.security.users is skipped.
quarkus.oauth2.client-secret
The OAuth2 client secret used to validate the token. file.enabled

The le realm is enabled. (default: false )


quarkus.oauth2.introspection-url
URL used to validate the token and gather the authentication file.auth-mechanism
claims. The authentication mechanism. ( default: BASIC )

quarkus.oauth2.role-claim file.realm-name
The claim that is used in the endpoint response to load the roles The authentication realm name. (default: Quarkus )
((default: scope )
file.plain-text
If passwords are in plain or in MD5. (default: false ) You still need to add the database driver (ie jdbc-h2 ).
principal-query.bcrypt-password-mapper.salt-index
file.users You need to con gure JDBC and Elytron JDBC Realm: The index column containing the Bcrypt salt. (default: 0 )
Classpath resource of user/password. (default:
users.properties ) quarkus.datasource.url= principal-query.bcrypt-password-mapper.salt-encoding
quarkus.datasource.driver=org.h2.Driver A string referencing the salt encoding ( BASE64 or HEX ). (default:
file.roles quarkus.datasource.username=sa BASE64 )
quarkus.datasource.password=sa
Classpath resource of user/role. (default: roles.properties )
principal-query.bcrypt-password-mapper.iteration-count-index
quarkus.security.jdbc.enabled=true
Embedded Realm quarkus.security.jdbc.principal-query.sql= The index column containing the Bcrypt iteration count. (default:
0)
SELECT u.password, u.role FROM test_user u WHERE u.user
You can embed user/password/role in the same
=?
application.properties : For multiple datasources you can use the datasource name in the
quarkus.security.jdbc.principal-query
.clear-password-mapper.enabled=true properties:
quarkus.security.users.embedded.enabled=true quarkus.security.jdbc.principal-query
quarkus.security.users.embedded.plain-text=true .clear-password-mapper.password-index=1 quarkus.datasource.url=
quarkus.security.users.embedded.users.scott=jb0ss quarkus.security.jdbc.principal-query quarkus.security.jdbc.principal-query.sql=
quarkus.security.users.embedded.roles.scott=admin,tester,us .attribute-mappings.0.index=2
er quarkus.security.jdbc.principal-query quarkus.datasource.permissions.url=
quarkus.security.users.embedded.auth-mechanism=BASIC .attribute-mappings.0.to=groups quarkus.security.jdbc.principal-query.permissions.sql=

IMPORTANT: If plain-text is set to false (or omitted) then


passwords must be stored in the form MD5
You need to set the index (1-based) of password and role. Security with JPA
( username :`realm`:`password`). Elytron JDBC Realm con guration properties. Pre x
You can also protect endpoints and store identities in a database
quarkus.security.jdbc is skipped.
Pre x quarkus.security.users.embedded is skipped. using JPA.
auth-mechanism
algorithm mvn quarkus:add-extension
The authentication mechanism. (default: BASIC )
Determine which algorithm to use. Possible values: DIGEST_MD5 , -Dextensions="security-jpa"
DIGEST_SHA , DIGEST_SHA_256 , DIGEST_SHA_384 , DIGEST_SHA_512 ,
realm-name
DIGEST_SHA_512_256 . (default: DIGEST_MD5 )
The authentication realm name. (default: Quarkus )
Also you might require jdbc-postgresql , resteasy ,
file.enabled
enabled hibernate-orm-panache .
The le realm is enabled. (default: false )
If the properties store is enabled. (default: false )

file.auth-mechanism
principal-query.sql
The authentication mechanism. (default: BASIC )
The sql query to nd the password.
file.realm-name
principal-query.datasource
The authentication realm name. (default: Quarkus )
The data source to use.
file.plain-text
principal-query.clear-password-mapper.enabled
If passwords are in plain or in MD5. (default: false )
If the clear-password-mapper is enabled. (default: false )

file.users.*
principal-query.clear-password-mapper.password-index
* is user and value is password.
The index of column containing clear password. (default: 1 )
file.roles.*
principal-query.bcrypt-password-mapper.enabled
* is user and value is role.
If the bcrypt-password-mapper is enabled. (default: false )

Security with a JDBC Realm principal-query.bcrypt-password-mapper.password-index


The index of column containing password hash. (default: 0 )
You can also protect endpoints and store identities in a database.
principal-query.bcrypt-password-mapper.hash-encoding
mvn quarkus:add-extension
A string referencing the password hash encoding ( BASE64 or HEX ).
-Dextensions="elytron-security-jdbc"
(default: BASE64 )
The identi er ( baseFilter ) which correlates to the provided user
@io.quarkus.security.jpa.UserDefinition quarkus.security.ldap.enabled=true
(default: uid )
@Table(name = "test_user") quarkus.security.ldap.dir-context.principal=uid=tool,ou=acc
@Entity ounts,o=YourCompany,c=DE
identity-mapping.search-base-dn
public class User extends PanacheEntity { quarkus.security.ldap.dir-context.url=ldaps://ldap.server.l
@io.quarkus.security.Username ocal The dn where we look for users.
public String name; quarkus.security.ldap.dir-context.password=PASSWORD
quarkus.security.ldap.identity-mapping.rdn-identifier=uid identity-mapping.attribute-mappings.<id>.from
@io.quarkus.security.Password quarkus.security.ldap.identity-mapping.search-base-dn=ou=us The roleAttributeId from which is mapped
public String pass; ers,ou=tool,o=YourCompany,c=DE
quarkus.security.ldap.identity-mapping.attribute-mapping identity-mapping.attribute-mappings.<id>.to
@ManyToMany s."0".from=cn
The identi er whom the attribute is mapped to (default: gropus )
@Roles quarkus.security.ldap.identity-mapping.attribute-mapping
public List<Role> roles = new ArrayList<>(); s."0".to=groups
identity-mapping.attribute-mappings.<id>.filter
quarkus.security.ldap.identity-mapping.attribute-mapping
public static void add(String username, String passwor s."0".filter=(member=uid={0}) The lter ( roleFilter )
d) { quarkus.security.ldap.identity-mapping.attribute-mapping
User user = new User(); s."0".filter-base-dn=ou=roles,ou=tool,o=YourCompany,c=DE identity-mapping.attribute-mappings.<id>.filter-base-dn
user.username = username; The lter base dn ( rolesContextDn )
user.password = BcryptUtil.bcryptHash(password);
user.persist();
}
Testing Vault
} There is a Quarkus Test Resource that starts and stops InMemory
Quarkus integrates with Vault to manage secrets or protecting
LDAP server before and after test suite. It is running in localhost
@Entity sensitive data.
with dc=quarkus,dc=io and binding credentials
public class Role extends PanacheEntity { ( "uid=admin,ou=system", "secret" ). Imports LDIF from a le located
at root of the classpath named quarkus-io.ldif . mvn quarkus:add-extension
@ManyToMany(mappedBy = "roles") -Dextensions="vault"
public List<ExternalRolesUserEntity> users; Register dependency io.quarkus:quarkus-test-ldap:test.

@io.quarkus.security.RolesValue And annotate the test:


And con guring Vault in application.properties :
public String role;
} @QuarkusTestResource(io.quarkus.test.ldap.LdapServerTestRes
# vault url
ource.class)
quarkus.vault.url=http://localhost:8200
public class ElytronLdapExtensionTestResources {
You need to con gure JDBC: }
quarkus.vault.authentication.userpass.username=
bob
quarkus.datasource.url=jdbc:postgresql:security_jpa quarkus.vault.authentication.userpass.password=
quarkus.datasource.driver=org.postgresql.Driver Elytron LDAP Realm con guration properties. Pre x sinclair
quarkus.datasource.username=quarkus quarkus.security.ldap is skipped.
quarkus.datasource.password=quarkus # path within the kv secret engine
enabled quarkus.vault.secret-config-kv-path=
quarkus.hibernate-orm.database.generation=drop-and-create Enable the LDAP elytron module (default: false ) myapps/vault-quickstart/config
quarkus.vault.secret-config-kv-prefix.singer.paths=
realm-name multi/singer1, multi/singer2

Security with LDAP The elytron realm name (default: Quarkus )

direct-verification vault kv put secret/myapps/vault-quickstart/config a-private-


You can also protect endpoints and store identities in a database
key=123456
using LDAP. Provided credentials are veri ed against LDAP (default: true )

vault kv put secret/multi/singer1 firstname=paul


mvn quarkus:add-extension dir-context.url
-Dextensions="elytron-security-ldap" The url of the LDAP server.
@ConfigProperty(name = "a-private-key")
String privateKey;
dir-context.principal
User ( bindDn ) which is used to connect to LDAP server. @ConfigProperty(name = "singer.firstname")
String firstName;
dir-context.password
The password ( bindCredential ) which belongs to the principal.
You can access the KV engine programmatically:
identity-mapping.rdn-identifier
@Inject @Inject @Inject
VaultKVSecretEngine kvSecretEngine; VaultTransitSecretEngine transit; VaultSystemBackendEngine vaultSystemBackendEngine;

kvSecretEngine.readSecret("myapps/vault-quickstart/" + vaul transit.encrypt("my_encryption", text); @Inject


tPath).toString(); transit.decrypt("my_encryption", text).asString(); VaultKubernetesAuthService vaultKubernetesAuthService;
transit.sign("my-sign-key", text);
Map<String, String> secrets; String rules = "path \"transit/*\" {\n" +
kvSecretEngine.writeSecret("myapps/vault-quickstart/crud", " capabilities = [ \"create\", \"read\", \"updat
secrets); e\" ]\n" +
Transit Key
"}";
kvSecretEngine.deleteSecret("myapps/vault-quickstart/crud" String policyName = "sys-test-policy";
); @Inject
VaultTransitSecretEngine transit; vaultSystemBackendEngine.createUpdatePolicy(policyName, rul
es);
transit.createKey(KEY_NAME, new KeyCreationRequestDetail().
Fetching credentials DB setExportable(true)); vaultKubernetesAuthService
transit.readKey(KEY_NAME); .createRole(roleName, new VaultKubernetesAuthRole()
With the next kv vault kv put secret/myapps/vault-quickstart/db
transit.listKeys();
password=connor .setBoundServiceAccountNames(boundServiceAccountN
transit.exportKey(KEY_NAME, VaultTransitExportKeyType.encry ames)
ption, null); .setBoundServiceAccountNamespaces(boundServiceAcc
quarkus.vault.credentials-provider.mydatabase.kv-path= transit.updateKeyConfiguration(KEY_NAME, new KeyConfigReque ountNamespaces)
myapps/vault-quickstart/db stDetail().setDeletionAllowed(true)); .setTokenPolicies(tokenPolicies));
transit.deleteKey(KEY_NAME);
quarkus.datasource.db-kind=
postgresql
quarkus.datasource.username= Vault con guration properties. Pre x quarkus.vault is skipped.
Vault TOTP
sarah
quarkus.datasource.credentials-provider= url
TOTP secret engine is supported by using
mydatabase Vault server URL
io.quarkus.vault.VaultTOTPSecretEngine class:
quarkus.datasource.jdbc.url=
jdbc:postgresql://localhost:5432/mydatabase authentication.client-token
@Inject
VaultTOTPSecretEngine vaultTOTPSecretEngine;
Vault token to access

No password is set as it is fetched from Vault. CreateKeyParameters createKeyParameters = new CreateKeyPara authentication.app-role.role-id

meters("Google", "test@gmail.com"); Role Id for AppRole auth


Dynamic credentials are also supported:
createKeyParameters.setPeriod("30m");
authentication.app-role.secret-id
Running the following dynamic database con g in Vault:
/** Generate Key (QR code) */ Secret Id for AppRole auth
vault write database/config/mydb plugin_name=postgresql-database- final Optional<KeyDefinition> myKey = vaultTOTPSecretEngine
plugin ….. .createKey("my_
authentication.app-role.secret-id-wrapping-token
key_2", createKeyParameters);
Wrapping token containing a Secret Id. secret-id and secret-id-
You can con gure as:
wrapping-token are exclusive.
/** Generate key number to login */
final String keyCode = vaultTOTPSecretEngine.generateCode(
quarkus.vault.credentials-provider authentication.userpass.username
"my_key_2");
.mydatabase.database-credentials-role=mydbrole
Username for userpass auth
/** Login logic */
quarkus.datasource.db-kind=
boolean valid = vaultTOTPSecretEngine.validateCode("my_key_ authentication.userpass.password
postgresql
2", keyCode); Password for userpass auth
quarkus.datasource.credentials-provider=
mydatabase
quarkus.datasource.jdbc.url= authentication.userpass.password-wrapping-token
jdbc:postgresql://localhost:5432/mydatabase Vault Provisioning Wrapping token containing a password. password and password-
wrapping-token are exclusive.
Vault extension offers façade classes to Vault provisioning
functions:
Username and password are fetched from Vault authentication.kubernetes.role
Kubernetes authentication role
Transit
authentication.kubernetes.jwt-token-path
Location of the le containing the Kubernetes JWT token

renew-grace-period
Renew grace period duration (default: 1H )
quarkus.kms.endpoint-override=http://localhost:8011 <dependency>
quarkus.kms.aws.region=us-east-1 <groupId>software.amazon.awssdk</groupId>
secret-config-cache-period
quarkus.kms.aws.credentials.type=static <artifactId>url-connection-client</artifactId>
Vault con g source cache period (default: 10M ) quarkus.kms.aws.credentials.static-provider.access-key-id=t </dependency>
est-key
secret-config-kv-path quarkus.kms.aws.credentials.static-provider.secret-access-k
Vault path in kv store. List of paths is supported in CSV ey=test-secret
or Apache HTTP:

log-confidentiality-level
<dependency>
Used to hide con dential infos. low , medium , high (default: You need to set a HTTP client either URL Connection : <groupId>software.amazon.awssdk</groupId>
medium ) <artifactId>apache-client</artifactId>
<dependency> </dependency>
kv-secret-engine-version <groupId>software.amazon.awssdk</groupId>
Kv secret engine version (default: 1) <artifactId>url-connection-client</artifactId>
</dependency>
And you need to add the asynchronous Netty client:
kv-secret-engine-mount-path Kv secret engine path (default: secret )

<dependency>
tls.skip-verify or Apache HTTP: <groupId>software.amazon.awssdk</groupId>
Allows to bypass certi cate validation on TLS communications <artifactId>netty-nio-client</artifactId>
(default: false ) <dependency> </dependency>
<groupId>software.amazon.awssdk</groupId>
tls.ca-cert <artifactId>apache-client</artifactId>
Certi cate bundle used to validate TLS communications </dependency>
@Inject
tls.use-kubernetes-ca-cert
IamClient client;

TLS will be active (default: true )


quarkus.sqs.sync-client.type=apache @Inject
IamAsyncClient async;
connect-timeout
Tiemout to establish a connection (default: 5S )
You can go async by using Mutiny:
read-timeout quarkus.iam.endpoint-override=${iam.url}
@Inject quarkus.iam.aws.region=us-east-1
Request timeout (default: 1S )
software.amazon.awssdk.services.kms.KmsAsyncClient kms; quarkus.iam.aws.credentials.type=static
quarkus.iam.aws.credentials.static-provider.access-key-id=t
credentials-provider."credentials-provider".database-credentials-
Uni.createFrom().completionStage( est-key
role
kms.encrypt(req -> req.keyId(keyArn).plaintext(SdkByte quarkus.iam.aws.credentials.static-provider.secret-access-k
Database credentials role s.fromUtf8String(data)) ey=test-secret
))
credentials-provider."credentials-provider".kv-path
A path in vault kv store, where we will nd the kv-key Con guration properties are the same as Amazon DynamoDB but
And you need to add the asynchronous Netty client: changing the pre x from dynamodb to iam .
credentials-provider."credentials-provider".kv-key
Key name to search in vault path kv-path (default: password ) <dependency>
<groupId>software.amazon.awssdk</groupId>
Amazon KMS <artifactId>netty-nio-client</artifactId>
</dependency>

mvn quarkus:add-extension
-Dextensions="amazon-kms"
Con guration properties are the same as Amazon DynamoDB but
changing the pre x from dynamodb to kms .

@Inject Amazon IAM


KmsClient kms;

mvn quarkus:add-extension
kms.encrypt(req -> req.keyId(keyArn).plaintext(
-Dextensions="quarkus-amazon-iam"
SdkBytes.fromUtf8String(data))).ciphertextBlob();

You need to set a HTTP client either URL Connection :


HTTP Con guration The le path to a service certi cate or certi cate chain in PEM enable-compression
format. Relative to src/main/resources . If responses should be compressed.
You can con gure HTTP parameters. Using quarkus.http pre x:
ssl.certificate.key-file read-timeout
cors The le path to the corresponding certi cate private key in PEM Http connection read timeout for blocking IO. (default: 60s )
Enable CORS. (default: false ) format. Relative to src/main/resources .
body.handle-file-uploads
cors.origins ssl.certificate.key-store-file
If the les sent using multipart/form-data will be stored locally.
CSV of origins allowed. (dedault: Any request valid.) The key store contains the certi cate information. Relative to (default: true )
src/main/resources .
cors.methods body.uploads-directory
ssl.certificate.key-store-file-type
CSV of methods valid. (default: Any method valid.) The directory where the les sent using multipart/form-data
The key store type. It is automatically detected based on the le should be stored. (default: file-uploads )
cors.headers name or can be set manually. Supported values are: JKS , JCEKS ,
P12 , PKCS12 or PFX .
CSV of valid allowed headers. (default: Any requested header body.merge-from-attributes
valid.) If the form attributes should be added to the request parameters.
ssl.certificate.key-store-password
(default: true )
cors.exposed-headers The password to open the key store le.
CSV of valid exposed headers. body.delete-uploaded-files-on-end
ssl.certificate.trust-store-file The trust store location which
If the uploaded les should be removed after serving the request.
contains the certi cate information of the certi cates to trust.
port
Relative to src/main/resources .
The HTTP port. (default: 8080 ) body.preallocate-body-buffer
ssl.certificate.trust-store-file-type If the body buffer should pre-allocated based on the Content-
test-port The trust store type. It is automatically detected based on the le Length header value. (default: 1K )
The HTTP test port. (default: 8081 ) name or can be set manually.
auth.session.encryption-key
host ssl.certificate.trust-store-password The encryption key that is used to store persistent logins.
The HTTP host. (default: 0.0.0.0 ) The password to open the trust store le.
so-reuse-port
host-enabled ssl.cipher-suites Enable socket reuse port.
Enable listening to host:port. (default: true ) A list of strings of cipher suites to use. If not provided, a
reasonable default is selected. tcp-quick-ack
ssl-port Enable tcp quick ack.
The HTTPS port. (default 8443 ) ssl.protocols

The list of protocols to explicitly enable. (default: TLSv1.3 and tcp-cork


test-ssl-port TLSv1.2 ). Enable tcp cork.
The HTTPS port used to run tests. (default 8444 )
ssl.client-auth tcp-fast-open
proxy-address-forwarding Con gures the engine to require/request client authentication. Enable tcp fast open.
The address, scheme etc will be set from headers forwarded by Possible values are: none , request and required . (default: none ).
the proxy server. domain-socket
io-threads
Path to a unix domain socket. (default:
allow-forwarded The number if IO threads used to perform IO. /var/run/io.quarkus.app.socket )
Proxy address forwarding is enabled then the standard Forwarded
header will be used, rather than the more common but not limits.max-header-size domain-socket-enabled
standard X-Forwarded-For . The maximum length of all headers. (default: 20k ) Enables domain socket.

insecure-requests limits.max-body-size record-request-start-time


If insecure requests are allowed. Possible values: enabled , The maximum size of a request body. (default: 10M ) If enabled then start time will be recorded to enable logging of
redirect , disable . (default: enabled ) total request time. (default: false )
limits.max-chunk-size
http2 The max HTTP chunk size. access-log.enabled
Enables HTTP/2. (default: true ) If access logging is enabled. (default: false )
limits.max-initial-line-length
ssl.port The maximum length of the initial line. (default: 4096 ) access-log.pattern
The HTTPS port. (default: 8443 ) The access log pattern. (default: common )
idle-timeout
ssl certificate file Htt ti idl ti t (d f lt ) l l t fil
If logging should be done to a separate le. (default: false )
@Path("/book") @Target({ElementType.METHOD})
public class BookResource { @Retention(RetentionPolicy.RUNTIME)
access-log.base-file-name
@HttpMethod("LOCK")
The access log le base name. (default: quarkus ) @GET public @interface LOCK {
@Produces(MediaType.APPLICATION_JSON) }
access-log.log-directory public List<Book> getAllBooks() {}
The log directory to use when logging access to a le. @LOCK
@POST public void lockIt() {}
access-log.log-directory
@Produces(MediaType.APPLICATION_JSON) }
public Response createBook(Book book) {}
The log directory to use when logging access to a le.
@DELETE
access-log.log-suffix Injecting
@Path("{isbn}")
The log le su x. (default: .log ) @Produces(MediaType.APPLICATION_JSON) Using @Context annotation to inject JAX-RS and Servlet information.
public Response deleteBook(
access-log.category @PathParam("isbn") String isbn) {}
@GET
The log category to use if logging is being done via the standard public String getBase(@Context UriInfo uriInfo) {
log mechanism. (default: io.quarkus.http.access-log ) return uriInfo.getBaseUri();
@GET
}
access-log.rotate
@Produces(MediaType.APPLICATION_JSON)
@Path("search")
If the log should be rotated daily. (default: true )
public Response searchBook(
@QueryParam("description") String description) {} Possible injectable objects: SecurityContext , Request , Application ,
same-site-cookie.<name>.case-sensitive Configuration , Providers , ResourceContext , ServletConfig ,
}
If the cookie pattern is case sensitive. ServletContext , HttpServletRequest , HttpServletResponse ,
HttpHeaders , Urinfo , SseEventSink and Sse .
same-site-cookie.<name>.value
To get information from request: HTTP Filters
The value to set in the samesite attribute.
@PathParam
HTTP request and response can be intercepted to manipulate the
same-site-cookie.<name>.enable-client-checker Gets content from request URI. (example: /book/{id} metadata (ie headers, parameters, media type, …) or abort a
Some User Agents break when sent SameSite=None, this will @PathParam("id") ) request. You only need to implement the next
detect them and avoid sending the value. (default: true ) ContainerRequestFilter and ContainerResponseFilter JAX-RS
@QueryParam interfaces respectively.
same-site-cookie.<name>.add-secure-for-none Gets query parameter. (example: /book?desc=""
If this is true then the 'secure' attribute will automatically be sent @QueryParam("desc) ) @Provider
on cookies with a SameSite attribute of None. (default: true ) public class LoggingFilter
@FormParam implements ContainerRequestFilter {
If metrics extension is registered, you can enable to get HTTP Gets form parameter.
metrics by setting quarkus.resteasy.metrics.enabled to true. @Context
@MatrixParam
UriInfo info;
JAX-RS Get URI matrix parameter. (example: @Context
/book;author=mkyong;country=malaysia )
HttpServletRequest request;
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 @CookieParam
@Override
Servlet.
Gets cookie param by name. public void filter(ContainerRequestContext context) {
It is important to know that if you want to use any feature that final String method = context.getMethod();
implies a Servlet (ie Servlet Filters) then you need to add the @HeaderParam final String path = info.getPath();
quarkus-undertow extension to switch back to the Servlet Gets header parameter by name. final String address = request.getRemoteAddr();
ecosystem but generally speaking, you don’t need to add it as System.out.println("Request %s %s from IP %s",
everything else is well-supported. Valid HTTP method annotations provided by the spec are: @GET ,
method, path, address);
@POST , @PUT , @DELETE , @PATCH , @HEAD and @OPTIONS .
}

You can create new annotations that bind to HTTP methods not }
de ned by the spec.

Exception Mapper

You can map exceptions to produce a custom output by


implementing ExceptionMapper interface:
@Provider import io.quarkus.vertx.http.runtime.filters.Filters; @ApplicationScoped
public class ErrorMapper import io.vertx.ext.web.Router; public class MyDeclarativeRoutes {
implements ExceptionMapper<Exception> { import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.event.Observes; @Route(path = "/hello", methods = HttpMethod.GET)
@Override public void greetings(RoutingContext rc) {
public Response toResponse(Exception exception) { @ApplicationScoped String name = rc.request().getParam("name");
int code = 500; public class MyBean { if (name == null) {
if (exception instanceof WebApplicationException) { name = "world";
code = ((WebApplicationException) exception) public void filters( }
.getResponse().getStatus(); @Observes Filters filters) { rc.response().end("hello " + name);
} filters }
return Response.status(code) .register(
.entity( rc -> { @RouteFilter(20)
Json.createObjectBuilder() rc.response() void filter(RoutingContext rc) {
.add("error", exception.getMessage()) .putHeader("X-Filter", "filter 1"); rc.response().putHeader("X-Filter", "filter 2");
.add("code", code) rc.next(); rc.next();
.build() }, }
) 10);
.build(); } @Route
} String hello(@Param Optional<String> name) {}
} public void routes(
@Observes Router router) { @Route
router String helloFromHeader(@Header("My-Header") String head
.get("/") er) {}
Caching
.handler(rc -> rc.response().end("OK"));
Annotations to set Cache-Control headers: } @Route
} String createPerson(@Body Person person) {}

@Produces(MediaType.APPLICATION_JSON)
}
@org.jboss.resteasy.annotations.cache.NoCache
public User me() {} Declarative

You can use @Route annotation to use reactive routes and


@Produces(MediaType.APPLICATION_JSON)
@RouteFilter to sue reactive lters in a declarative way:
GraphQL
@org.jboss.resteasy.annotations.cache.Cache(
maxAge = 2000, Quarkus integrates with GraphQL using MicroPro le GraphQL
noStore = false ./mvnw quarkus:add-extension integration.
) -Dextensions="quarkus-vertx-web"
public User you() {}
./mvnw quarkus:add-extension
-Dextensions="graphql"

Vert.X Filters and Routes


@GraphQLApi
Programmatically
public class FilmResource {
You can also register Vert.X Filters and Router programmatically
inside a CDI bean: @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 extendig io.smallrye.mutiny.vertx.core.AbstractVerticle . ssl.key
name. The le path to the corresponding certi cate private key le in
You can see the full schema at /graphql/schema.graphql . Also
GZip Support PEM format.
GraphiQL UI is enabled at dev and test mode at /graphql-ui/ .
You can con gure Quarkus to use GZip in the ssl.key-store

Extension can be con gured with the follwoing paramters pre xed application.properties le using the next properties with An optional key store which holds the certi cate information
with quarkus.smallrye-graphql . quarkus.resteasy su x: instead of specifying separate les.

root-path gzip.enabled
ssl.key-store-type
The rootPath under which queries will be served. (default: EnableGZip. (default: false )
An optional parameter to specify the type of the key store le.
/graphql )
gzip.max-input
ssl.key-store-password
root-path-ui Con gure the upper limit on de ated request body. (default: 10M )
A parameter to specify the password of the key store le.
The path where GraphQL UI is available. (default: /graphql-ui ) (default: password )
GRPC
always-include-ui ssl.trust-store
The path where GraphQL UI is available. (default: /graphql-ui ) Quarkus integrates with gRPC: Trust store which holds the certi cate information of the
certi cates to trust
root-path-ui ./mvnw quarkus:add-extension
Always include the UI. By default this will only be included in dev -Dextensions="quarkus-grpc" ssl.trust-store-type
and test. (default: false ) Parameter to specify type of the trust store le.

enable-ui Then you need to con gure build tool with gRPC plugins. In the ssl.trust-store-password
If GraphQL UI should be enabled. (default: false ) case of Maven, the kr.motd.maven:os-maven-plugin extension and A parameter to specify the password of the trust store le.
org.xolstice.maven.plugins:protobuf-maven-plugin
metrics.enabled ssl.cipher-suites
Protos les are stored at src/main/proto .
Enable metrics. (default: false ) A list of the cipher suites to use.
When java les are created two service implementations are
Vert.X Verticle provided: one with default gRPC API and other with Mutiny support. ssl.protocols

The list of protocols to explicitly enable. (default:


Vert.X Verticles are also supported: With quarkus.grpc.server pre x, the next con guration properties TLSv1.3,TLSv1.2 )
can be set:
@ApplicationScoped transport-security.certificate
port
public class VerticleDeployer { The path to the certi cate le.
The gRPC Server port. (default: 9000 )

@Inject transport-security.key
host
Vertx vertx;
The path to the private key le.
The gRPC server host. (default: 0.0.0.0 )
public void init(@Observes StartupEvent ev) {
To consume the service:
CountDownLatch latch = new CountDownLatch(1); handshake-timeout
vertx.deployVerticle(BareVerticle::new, The gRPC handshake timeout.
new DeploymentOptions() @GrpcService("hello")
.setConfig( GreeterGrpc.GreeterBlockingStub client;
max-inbound-message-size
new JsonObject()
The max inbound message size in bytes. @GrpcService("hello")
.put("id", "bare")
) io.grpc.Channel channel;
plain-text
)
.thenAccept(x -> latch.countDown()); Use plain text. (default: true )

Some con guration example to set the host and the SSL
latch.countDown(); alpn parameters:
} TWhether ALPN should be used. (default: true )
}
quarkus.grpc.clients.hello.host=localhost
enable-reflection-service quarkus.grpc.clients.hello.plain-text=false
Enables the gRPC Re ection Service. (default: false ) quarkus.grpc.clients.hello.ssl.certificate=src/main/resourc
Verticles can be: es/tls/client.pem
ssl.certificate quarkus.grpc.clients.hello.ssl.key=src/main/resources/tls/c
bare lient.key
The le path to a server certi cate or certi cate chain in PEM
extending io.vertx.core.AbstractVerticle .
format. quarkus.grpc.clients.hello.ssl.trust-store=src/main/resourc
es/tls/ca.pem
mutiny
Fault Tolerance If 3 (4 x 0.75) failures occur among the rolling window of 4
org.acme.quickstart.WorldClock/getNow/Retry/enabled=false
consecutive invocations then the circuit is opened for 1000 ms and
# Disable everything except fallback
Quarkus uses MicroPro le Fault Tolerance spec: then be back to half open. If the invocation succeeds then the
MP_Fault_Tolerance_NonFallback_Enabled=false
circuit is back to closed again.
./mvnw quarkus:add-extension You can use bulkahead pattern to limit the number of concurrent
-Dextensions="io.quarkus:quarkus-smallrye-fault-toleranc access to the same resource. If the operation is synchronous it MicroPro le Fault Tolerance integrates with MicroPro le
e" uses a semaphore approach, if it is asynchronous a thread-pool Metrics spec. You can disable it by setting
one. When a request cannot be processed BulkheadException is MP_Fault_Tolerance_Metrics_Enabled to false.
thrown. It can be used together with any other fault tolerance
annotation.
MicroPro le Fault Tolerance spec uses CDI interceptor and it can Observability
be used in several elements such as CDI bean, JAX-RS resource or
MicroPro le Rest Client. @Bulkhead(5) Health Checks
@Retry(maxRetries = 4,
To do automatic retries on a method: delay = 1000, Quarkus relies on MicroPro le Health spec to provide health
retryOn = BulkheadException.class) checks.
@Path("/api") WorldClock getNow(){}
@RegisterRestClient ./mvnw quarkus:add-extension
public interface WorldClockService { -Dextensions="io.quarkus:quarkus-smallrye-health"
@GET @Path("/json/cet/now")
Fault tolerance annotations:
@Produces(MediaType.APPLICATION_JSON)
@Retry(maxRetries = 2)
Annotation Properties By just adding this extension, an endpoint is registered to /q/health
WorldClock getNow();
} providing a default health check.
@Timeout unit

{
maxRetries , delay , delayUnit , "status": "UP",
You can set fallback code in case of an error by using @Fallback
maxDuration , durationUnit , "checks": [
annotation: @Retry
jitter , jitterDelayUnit , retryOn , ]
abortOn }
@Retry(maxRetries = 1)
@Fallback(fallbackMethod = "fallbackMethod")
WorldClock getNow(){}
@Fallback fallbackMethod To create a custom health check you need to implement the
public WorldClock fallbackMethod() { HealthCheck interface and annotate either with @Readiness (ready to

return new WorldClock(); process requests) or @Liveness (is running) annotations.


waitingTaskQueue (only valid in
} @Bulkhead
asynchronous)
@Readiness
public class DatabaseHealthCheck implements HealthCheck {
failOn , delay , delayUnit ,
@Override
fallbackMethodmust have the same parameters and return type as
requestVolumeThreshold ,
public HealthCheckResponse call() {
the annotated method. @CircuitBreaker
failureRatio , successThreshold
HealthCheckResponseBuilder responseBuilder =
You can also set logic into a class that implements FallbackHandler HealthCheckResponse.named("Database conn");
interface:
@Asynchronous try {
checkDatabaseConnection();
public class RecoverFallback
responseBuilder.withData("connection", true);
implements FallbackHandler<WorldClock> {
You can override annotation parameters via con guration le using responseBuilder.up();
@Override
property [classname/methodname/]annotation/parameter : } catch (IOException e) {
public WorldClock handle(ExecutionContext context) {
// cannot access the database
}
org.acme.quickstart.WorldClock/getNow/Retry/maxDuration=30 responseBuilder.down()
}
# Class scope .withData("error", e.getMessage());
org.acme.quickstart.WorldClock/Retry/maxDuration=3000 }
# Global return responseBuilder.build();
And set it in the annotation as value Retry/maxDuration=3000 }
@Fallback(RecoverFallback.class) . }

In case you want to use circuit breaker pattern:


You can also enable/disable policies using special parameter
enabled .
Builds the next output:
@CircuitBreaker(requestVolumeThreshold = 4,
failureRatio=0.75,
delay = 1000)
WorldClock getNow(){}
Health groups are supported to provide custom health checks
{ quarkus.smallrye-health.root-path=/hello
"status": "UP", quarkus.smallrye-health.liveness-path=/customlive
groups:
"checks": [ quarkus.smallrye-health.readiness-path=/customready
{ @io.smallrye.health.HealthGroup("mygroup1")
"name": "Database conn", public class SimpleHealthGroupCheck implements HealthCheck
"status": "UP", {
Automatic readiness probes
"data": { }
"connection": true Some default readiness probes are provided by default if any of the
} next features are added:
} You can ping grouped health checks by querying /group/mygroup1 .
] datasource
}
A probe to check database connection status. Group root path can be con gured:

kafka quarkus.smallrye-health.group-path=/customgroup
Since health checks are CDI beans, you can do: A probe to check kafka connection status. In this case you need
to enable manually by setting quarkus.kafka.health.enabled to
@ApplicationScoped true . Metrics
public class DatabaseHealthCheck {
mongoDB Quarkus can utilize the MicroPro le Metrics spec to provide metrics
@Liveness
A probe to check MongoDB connection status. support.
HealthCheck check1() {
return io.smallrye.health.HealthStatus
neo4j ./mvnw quarkus:add-extension
.up("successful-live"); -Dextensions="io.quarkus:quarkus-smallrye-metrics"
} A probe to check Neo4J connection status.

@Readiness artemis
HealthCheck check2() { A probe to check Artemis JMS connection status. The metrics can be read with JSON or the OpenMetrics format. An
return HealthStatus endpoint is registered automatically at /q/metrics providing default
metrics.
.state("successful-read", this::isReady) kafka-streams
}
Liveness (for stream state) and Readiness (topics created) MicroPro le Metrics annotations:
probes.
private boolean isReady() {}
@Timed
}
vault Tracks the duration.
A probe to check Vault conection status.
@SimplyTimed
You can ping liveness or readiness health checks individually by gRPC Tracks the duration without mean and distribution calculations.
querying /q/health/live or /q/health/ready .
A readiness probe for the gRPC services.
Quarkus comes with some HealthCheck implementations for @Metered
checking service status. Cassandra Tracks the frequency of invocations.
A readiness probe to check Cassandra connection status.
SocketHealthCheck: checks if host is reachable using a @Counted
socket. Redis Counts number of invocations.
UrlHealthCheck: checks if host is reachable using a Http URL A readiness probe to check Redis connection status.
connection. @Gauge
You can disable the automatic generation by setting Samples the value of the annotated object.
InetAddressHealthCheck: checks if host is reachable using <component>.health.enabled to false.
InetAddress.isReachable method. @ConcurrentGauge
quarkus.kafka-streams.health.enabled=false Gauge to count parallel invocations.
@Liveness quarkus.mongodb.health.enabled=false
HealthCheck check1() { quarkus.neo4j.health.enabled=false @Metric
return new UrlHealthCheck("https://www.google.com")
Used to inject a metric. Valid types Meter , Timer , Counter ,
.name("Google-Check");
Histogram . Gauge only on producer methods/ elds.
}
In the case of Vault you can pass parameters to modify the call of
the status endpoint in Vault.

If you want to override or set manually readiness/liveness probes, quarkus.vault.health.enabled=true


you can do it by setting health properties: quarkus.vault.health.stand-by-ok=true
quarkus.vault.health.performance-stand-by-ok=true
export.prometheus.path
@GET @Stereotype
//... @Retention(RetentionPolicy.RUNTIME) The path for the prometheus metrics endpoint (produces
@Timed(name = "checksTimer", @Target({ ElementType.TYPE, ElementType.METHOD, ElementTyp text/plain). (default: /q/metrics )
description = "A measure of how long it takes e.FIELD })
to perform a hello.", @Timed(name = "checksTimer", export.azuremonitor.enabled
unit = MetricUnits.MILLISECONDS) description = "A measure of how long it takes Support for export to Azure Monitor.
public String hello() {} to perform a hello.",
unit = MetricUnits.MILLISECONDS) export.azuremonitor.instrumentation-key
@Counted(name = "countWelcome", public @interface TimedMilliseconds {
The path for the azure monitor instrumentationKey.
description = "How many welcome have been performed.") }
public String hello() {}
export.statsd.enabled
Support for export to StatsD.
There is a tight integration with Micrometer in the form of an
@Gauge annotation returning a measure as a gauge. extension:
export.stackdriver.enabled
Micrometer metrics support. (default: true )
@Gauge(name = "hottestSauce", unit = MetricUnits.NONE, ./mvnw quarkus:add-extension
description = "Hottest Sauce so far.") -Dextensions="micrometer"
export.signalfx.enabled
public Long hottestSauce() {}
Micrometer metrics support. (default: true )

Add a micrometer dependency for the registry of your choosing:


export.signalfx.uri
Injecting a histogram using @Metric .
Signalfx URI.
<dependency>
@Inject <groupId>io.micrometer</groupId>
export.signalfx.access-token
@Metric(name = "histogram") <artifactId>micrometer-registry-prometheus</artifactId>
Histogram historgram; </dependency> Access Token.

binder.vertx.match-patterns

You can con gure Metrics: You can con gure Micrometer. Pre x is quarkus.micrometer : Comma-separated case-sensitive list of regular expressions
de ning Paths that should be matched and used as tags
enabled
quarkus.smallrye-metrics.path=/mymetrics
Micrometer metrics support. (default: true ) binder.vertx.ignore-patterns

Comma-separated case-sensitive list of regular expressions


registry-enabled-default de ning Paths that should be ignored / not measured.
Pre x is quarkus.smallrye-metrics .
Micrometer MeterRegistry discovery. (default: true )
export.datadog
path

The path to the metrics handler. (default: /q/metrics ) binder-enabled-default Datadog MeterRegistry con guration in Map<String, String>

Micrometer MeterBinder discovery. (default: true )


format.
extensions.enabled
export.jmx
Metrics are enabled or not. (default: true ) binder.vertx.enabled

Vert.x metrics support. JMX registry con guration properties in Map<String, String>
format.
micrometer.compatibility
Apply Micrometer compatibility mode. (default: false ) binder.mp-metrics.enabled
export.prometheus
Micropro le Metrics support.
Prometheus registry con guration properties in Map<String,
quarkus.hibernate-orm.metrics.enabled set to true exposes
String> format.
Hibernate metrics under vendor scope. binder.jvm

Micrometer JVM metrics support. (default: true )


quarkus.mongodb.metrics.enabled set to true exposes MongoDB export.stackdriver
metrics under vendor scope. Stackdriver registry con guration properties in Map<String,
binder.system
String> format.
You can apply metrics annotations via CDI stereotypes: Micrometer System metrics support. (default: true )

Tracing
export.datadog.enabled
Support for export to Datadog Support for Datadog. Quarkus can utilize the MicroPro le OpenTracing spec.

export.jmx.enabled ./mvnw quarkus:add-extension


Support for export to JMX Support for JMX. -Dextensions="io.quarkus:quarkus-smallrye-opentracing"

export.prometheus.enabled
Support for export to Prometheus. Requests sent to any endpoint are traced automatically.
This extension includes OpenTracing support and Jaeger tracer. Kafka Tracer Native Executable
Jaeger tracer con guration: Adds a span for each message sent to or received from a Kafka
You can build a native image by using GraalVM. The common use
topic.
case is creating a Docker image so you can execute the next
quarkus.jaeger.service-name=myservice commands:
quarkus.jaeger.sampler-type=const <dependency>
quarkus.jaeger.sampler-param=1 <groupId>io.opentracing.contrib</groupId>
./mvnw package -Pnative -Dquarkus.native.container-build=tr
quarkus.jaeger.endpoint=http://localhost:14268/api/traces <artifactId>opentracing-kafka-client<</artifactId>
ue
quarkus.jaeger.metrics.enabled=true </dependency>

docker build -f src/main/docker/Dockerfile.native


-t quarkus/getting-started .
@Traced annotation can be set to disable tracing at class or method And con gure it: docker run -i --rm -p 8080:8080 quarkus/getting-started
level.
...
Tracer class can be injected into the class. mp.messaging.outgoing.generated-price.topic=prices You can use quarkus.native.container-runtime to select the
container runtime to use. Now docker (default) and podman are the
@Inject # For Produces valid options.
Tracer tracer; mp.messaging.outgoing.generated-price.interceptor.classes=i
o.opentracing.contrib.kafka.TracingProducerInterceptor
tracer.activeSpan().setBaggageItem("key", "value"); ./mvnw package -Pnative -Dquarkus.native.container-runtime=
...
podman
# For consumers
mp.messaging.incoming.prices.interceptor.classes=io.opentra
You can disable Jaeger extension by using quarkus.jaeger.enabled cing.contrib.kafka.TracingConsumerInterceptor
property. To con gure native application, you can create a config directory at
the same place as the native le and place an
You can log the traceId , spanId and sampled in normal log: application.properties le inside. config/application.properties .
AWS XRay
SSL
quarkus.log.console.format=%d{HH:mm:ss} %-5p traceId=%X{tra If you are building native images, and want to use AWS X-Ray
ceId}, Tracing with your lambda you will need to include quarkus-amazon- To create a native image with SSL you need to copy SunEC library
spanId=%X{spanId}, sampled lambda-xray as a dependency in your pom.
and certi cates:
=%X{sampled} [%c{2.}] (%t) %s%e%n
Java 8:

Additional tracers FROM quay.io/quarkus/ubi-quarkus-native-image:{graalvm-vers


ion}-java8 as nativebuilder
JDBC Tracer RUN mkdir -p /tmp/ssl-libs/lib \
&& cp /opt/graalvm/jre/lib/security/cacerts /tmp/ssl-libs
Adds a span for each JDBC queries. \
&& cp /opt/graalvm/jre/lib/amd64/libsunec.so /tmp/ssl-lib
<dependency> s/lib/
<groupId>io.opentracing.contrib</groupId>
<artifactId>opentracing-jdbc</artifactId> FROM registry.access.redhat.com/ubi8/ubi-minimal
</dependency> WORKDIR /work/
COPY --from=nativebuilder /tmp/ssl-libs/ /work/
COPY target/*-runner /work/application
RUN chmod 775 /work /work/application
Con gure JDBC driver apart from tracing properties seen before:
EXPOSE 8080
CMD ["./application", "-Dquarkus.http.host=0.0.0.0", "-Djav
# add ':tracing' to your database URL a.library.path=/work/lib", "-Djavax.net.ssl.trustStore=/wor
quarkus.datasource.url= k/cacerts"]
jdbc:tracing:postgresql://localhost:5432/mydatabase
quarkus.datasource.driver=
io.opentracing.contrib.jdbc.TracingDriver
quarkus.hibernate-orm.dialect= Java 11:
org.hibernate.dialect.PostgreSQLDialect

OpenTelemetry

Quarkus integrates with the OpenTelemetry project. For exporting


traces to a Jaeger collector, use the quarkus-opentelemetry-
exporter-jaeger extension
If all character sets should be added to the native image. full-stack-traces
FROM quay.io/quarkus/ubi-quarkus-native-image:{graalvm-vers
ion}-java11 as nativebuilder If full stack traces are enabled in the resulting image.
graalvm-home
RUN mkdir -p /tmp/ssl-libs/lib \
&& cp /opt/graalvm/lib/security/cacerts /tmp/ssl-libs \ The location of the Graal distribution. enable-reports
&& cp /opt/graalvm/lib/libsunec.so /tmp/ssl-libs/lib/ If the reports on call paths and included
java-home packages/classes/methods should be generated.
FROM registry.access.redhat.com/ubi8/ubi-minimal The location of the JDK.
WORKDIR /work/ report-exception-stack-traces
COPY --from=nativebuilder /tmp/ssl-libs/ /work/ native-image-xmx If exceptions should be reported with a full stack trace.
COPY target/*-runner /work/application
The maximum Java heap to be used during the native image
RUN chmod 775 /work /work/application
generation. report-errors-at-runtime
EXPOSE 8080
CMD ["./application", "-Dquarkus.http.host=0.0.0.0", "-Djav If errors should be reported at runtime.
debug-build-process
a.library.path=/work/lib", "-Djavax.net.ssl.trustStore=/wor
k/cacerts"] If the native image build should wait for a debugger to be enable-dashboard-dump
attached before running. Generate the report les for GraalVM Dashboard.

publish-debug-build-process-port
Inclusion of resources resources.includes
If the debug port should be published when building with docker A comma separated list of globs to match resource paths that
By default, no resources are included in native executable. and debug-build-process. (default: true ) should be added to the native image.
quarkus.native.resources.includes allows to set glob expressions to
include resources based on src/main/resources path. cleanup-server resources.excludes
If the native image server should be restarted. A comma separated list of globs to match resource paths that
Given src/main/resources/foo/selected.png :
should exclude to the native image.
enable-isolates
quarkus.native.resources.includes=foo/**
If isolates should be enabled. (default: true ) debug.enabled

If debug is enabled and debug symbols are generated.


enable-fallback-images
Exclusion of resources
If a JVM based 'fallback image' should be created if native image Container Images Creation
By default, no resources are excluded. fails.
You can levarage to Quarkus to generation and release of Docker
enable-server containers. It provides several extensions to make it so.
quarkus.native.resources.excludes = foo/**
If the native image server should be used.
mvn clean package
auto-service-loader-registration -Dquarkus.container-image.build=true
Native con guration properties pre xed with quarkus.native :
If all META-INF/services entries should be automatically -Dquarkus.container-image.push=true
additional-build-args registered. -Dquarkus.container-image.registry=quay.io

Additional arguments to pass to the build process.


dump-proxies

enable-http-url-handler If the bytecode of all proxies should be dumped for inspection. Pre x is quarkus.container-image :

If the HTTP url handler should be enabled. (default: true )


group
container-build

enable-https-url-handler If this build should be done using a container runtime. The group/repository of the image. (default: the ${user.name} )

If the HTTPS url handler should be enabled. name


remote-container-build

If this build is done using a remote docker daemon. The name of the image. (default: the application name)
enable-all-security-services
If all security services should be added to the native image. tag
builder-image

The docker image to use to do the image build. The tag of the image. (default: the application version)
user-language

De nes the user language used for building the native additional-tags
container-runtime
executable.
The container runtime that is used to do an image based build. Additional tags of the container image.
user-country ( docker , podman )
registry
De nes the user country used for building the native executable.
container-runtime-options The registry to use for pushing. (default: docker.io )

file-encoding Options to pass to the container runtime.


username
De nes the le encoding.
enable-vm-inspection The registry username.
If the resulting image should allow VM introspection
password ports Running ./mvnw package the Kubernetes resources are created at
The registry password. The ports to expose. target/kubernetes/ directory.

insecure user
Container Images Creation integrates with Kubernetes
extension, so no need of extra Kubernetes properties.
Flag to allow insecure registries. (default: false ) The user to use in generated image.
Generated resource is integrated with MicroPro le Health
build always-cache-base-image
annotations.
Boolean to set if image should be built. (default: false ) Controls the optimization which skips downloading base image
layers that exist in a target registry (default: false ). Also, you can customize the generated resource by setting the new
push values in application.properties :
Boolean to set if image should be pushed. (default: false ) appcds-builder-image

When AppCDS generation is enabled, if this property is set, then quarkus.kubernetes.namespace=mynamespace


Jib the JVM used to generate the AppCDS le will be the JVM
present in the container image. quarkus.kubernetes.replicas=3

./mvnw quarkus:add-extensions
platforms quarkus.kubernetes.labels.foo=bar
-Dextensions="quarkus-container-image-jib"
List of target platforms. (ie linux/amd64 ).
quarkus.kubernetes.readiness-probe.period-seconds=45

Quarkus copies any le under src/main/jib into the built container Docker
quarkus.kubernetes.mounts.github-token.path=/deployment/git
image. hub
./mvnw quarkus:add-extensions quarkus.kubernetes.mounts.github-token.read-only=true
Pre x is quarkus.container-image-jib : -Dextensions="quarkus-container-image-docker"
quarkus.kubernetes.secret-volumes.github-token.volume-name=
base-jvm-image
github-token
The base image to use for the jib build. (default: fabric8/java-
Pre x is quarkus.container-image-s2i : quarkus.kubernetes.secret-volumes.github-token.secret-name=
alpine-openjdk8-jre ) greeting-security
dockerfile-jvm-path quarkus.kubernetes.secret-volumes.github-token.default-mode
base-native-image =420
Path to the JVM Docker le. (default:
The base image to use for the native build. (default: ${project.root}/src/main/docker/Dockerfile.jvm )
registry.access.redhat.com/ubi8/ubi-minimal ) quarkus.kubernetes.config-map-volumes.github-token.config-m
ap-name=my-secret
dockerfile-native-path
jvm-arguments
Path to the native Docker le. (default: quarkus.kubernetes.expose=true
The arguments to pass to java. (default: - ${project.root}/src/main/docker/Dockerfile.native ) quarkus.kubernetes.ingress.expose=true
Dquarkus.http.host=0.0.0.0,-
quarkus.kubernetes.ingress.host=example.com
Djava.util.logging.manager=org.jboss.logmanager.LogManager ) S2I
quarkus.kubernetes.env.vars.my-env-var=foobar
native-arguments
./mvnw quarkus:add-extensions quarkus.kubernetes.env.configmaps=my-config-map,another-con
The arguments to pass to the native application. (default: - -Dextensions="quarkus-container-image-s2i" fig-map
Dquarkus.http.host=0.0.0.0 ) quarkus.kubernetes.env.secrets=my-secret,my-other-secret

environment-variables quarkus.kubernetes.resources.requests.memory=64Mi
Pre x is quarkus.container-image-docker :
Map of environment variables. quarkus.kubernetes.resources.requests.cpu=250m
base-jvm-image
quarkus.kubernetes.resources.limits.memory=512Mi
jvm-entrypoint
quarkus.kubernetes.resources.limits.cpu=1000m
The base image to use for the s2i build. (default: fabric8/java-
A custom entry point of the container image in JVM mode. alpine-openjdk8-jre )

native-entrypoint base-native-image All possible values are explained at


https://quarkus.io/guides/kubernetes#con guration-options.
A custom entry point of the container image in native mode. The base image to use for the native build. (default:
registry.access.redhat.com/ubi8/ubi-minimal )
Labels and Annotations
labels

Custom labels to add to the generated image. Kubernetes The generated manifest use the Kubernetes recommended labels
and annotations.
base-registry-username Quarkus can use Dekorate to generate Kubernetes resources.
The username to use to authenticate with the registry used to
pull the base JVM image. ./mvnw quarkus:add-extensions
-Dextensions="quarkus-kubernetes"
base-registry-password

The password to use to authenticate with the registry used to pull


openshift Datasource con guration part is absent as it is aut-discovered by
"labels" : {
https://quarkus.io/guides/kubernetes#openshift Quarkus.
"app.kubernetes.io/part-of" : "todo-app",
"app.kubernetes.io/name" : "todo-rest",
"app.kubernetes.io/version" : "1.0-rc.1" Knative Minikube
} https://quarkus.io/guides/kubernetes#knative
Quarkus has a Minikube extension which creates Kubernetes
"annotations": { Using Existing Resources manifests that are tailored for Minikube.
"app.quarkus.io/vcs-url" : "<some url>",
"app.quarkus.io/commit-id" : "<some git SHA>", You an provide your Kubernetes resources in form of yaml/json and ./mvnw quarkus:add-extension
} they will provide additional resources or be used as base for the -Dextensions="minikube"
generation process:

Resources are added in src/main/kubernetes directory with the


You can override the labels by using the next properties: Remember to execute eval $(minikube -p minikube docker-
target name ( kubernetes.json , openshift.json , knative.json , or the
yml equivalents) with one orm ore Kubernetes resources. Any env) to build images directly inside Minkube cluster.
quarkus.kubernetes.part-of=todo-app resource found will be added in the generated manifests. If one of
quarkus.kubernetes.name=todo-rest the provided resources has the same name as one of the generated OpenShift
quarkus.kubernetes.version=1.0-rc.1 ones, then the generated resource will be created on top of the
provided resource, respecting existing content. Instead of adding Kubernetes extension, set container image s2i
and the target to openshift for working with OpenShift, an
Or add new labels and/or annotations: To override the name of the generated resource you can use: extension grouping all of the is created:
quarkus.kubernetes.name , quarkus.openshift.name and
quarkus.knative.name .
quarkus.kubernetes.labels.foo=bar ./mvnw quarkus:add-extension
quarkus.kubernetes.annotations.foo=bar Deployment -Dextensions="openshift"

To deploy automatically the generated resources, you need to set


quarkus.container.deploy ag to true .
metrics Kubernetes Con guration Extension
When using metrics extension, Prometheus annotations are mvn clean package -Dquarkus.kubernetes.deploy=true
Integration between MicroPro le Con g spec and Con gMaps &
generated:
Secrets:

prometheus.io/scrape: "true"
If you set this ag to true , the build and push ags from ./mvnw quarkus:add-extensions
prometheus.io/path: /metrics
container-image are set to true too. -Dextensions="quarkus-kubernetes-config"
prometheus.io/port: "8080"

To deploy the application, the extension uses the


https://github.com/fabric8io/kubernetes-client. All options
Kubernetes Deployment Targets described at Kubernetes Client are valid here. quarkus.kubernetes-config.enabled=true
quarkus.kubernetes-config.config-maps=cmap1,cmap2
You can generate different resources setting the property Kubernetes Service Binding
quarkus.kubernetes.deployment-target .
Quarkus supports binding services to applications via the Service
Possible values are kubernetes , openshift and knative . The default Binding Speci cation for Kubernetes. @ConfigProperty(name = "some.prop1")
value is kubernetes . String someProp1;
The following Quarkus extensions support this feature:
Knative Properties @ConfigProperty(name = "some.prop2")
quarkus-jdbc-mariadb String someProp2;
Most of the Kubernetes properties are valid in Knative output by
just changing the kubernetes pre x to knative pre x (ie quarkus-jdbc-mssql
quarkus.kubernetes.readiness-probe.period-seconds to
quarkus.knative.readiness-probe.period-seconds ). quarkus-jdbc-mysql If the con g key is a Quarkus con guration le
application.properties / application.yaml , the content is parsed and
There are also speci c properties for Knative: quarkus-jdbc-postgresql each key of the con guration le is used as con g property.
quarkus-kafka-client List of Kubernetes Con g parameters.
quarkus.kubernetes.deployment-target=knative
quarkus.knative.revision-name=my-revision quarkus-smallrye-reactive-messaging-kafka quarkus.kubernetes-config as pre x is skipped in the next table.
quarkus.knative.traffic.my-revision.percentage=80

./mvnw quarkus:add-extensions enabled

-Dextensions="quarkus-kubernetes-service-binding" The application will attempt to look up the con guration from the
List of con guration options: API server. (default: false )

kubernetes fail-on-missing-config
https://quarkus io/guides/kubernetes#con guration options
The application will not start if any of the con gured con g watch-reconnect-interval
@Inject
sources cannot be located. (default: true ) Watch reconnect interval. (default: PT1S ) KubernetesClient client;

config-maps watch-reconnect-limit ServiceList myServices = client.services().list();


Con gMaps to look for in the namespace that the Kubernetes Maximum reconnect attempts. (default: -1 )
Client has been con gured for. Supports CSV. Service myservice = client.services()
connection-timeout .inNamespace("default")
namespace .withName("myservice")
Maximum amount of time to wait for a connection. (default:
Access to Con gMaps from a speci c namespace. .get();
PT10S )

secrets.enabled
CustomResourceDefinitionList crds = client
request-timeout
.customResourceDefinitions()
Whether or not con guration can be read from secrets. (default: Maximum amount of time to wait for a request. (default: PT10S ) .list();
false )

rolling-timeout dummyCRD = new CustomResourceDefinitionBuilder()


Kubernetes Client Maximum amount of time to wait for a rollout. (default: PT15M ) ...
.build()
Quarkus integrates with Fabric8 Kubernetes Client. http-proxy client.customResourceDefinitions()
.create(dummyCRD);
HTTP proxy used to access the Kubernetes.
./mvnw quarkus:add-extension
-Dextensions="quarkus-kubernetes-client" https-proxy
Testing
HTTPS proxy used to access the Kubernetes.
Quarkus provides a Kubernetes Mock test resource that starts a
List of Kubernetes client parameters. proxy-username
mock of Kubernetes API server and sets the proper environment
quarkus.kubernetes-client as pre x is skipped in the next table. Proxy username. variables needed by Kubernetes Client.

trust-certs proxy-password Register next dependency: io.quarkus:quarkus-test-kubernetes-


client:test .
Trust self-signed certi cates. (default: false ) Proxy password.

no-proxy @QuarkusTestResource(KubernetesMockServerTestResource.clas
master-url
s)
URL of Kubernetes API server. IP addresses or hosts to exclude from proxying
@QuarkusTest
public class KubernetesClientTest {
namesapce Or programmatically:
Default namespace. @MockServer
@Dependent private KubernetesMockServer mockServer;
ca-cert-file public class KubernetesClientProducer {

CA certi cate data. @Test


@Produces public void test() {
public KubernetesClient kubernetesClient() { final Pod pod1 = ...
client-cert-file
Config config = new ConfigBuilder() mockServer
Client certi cate le. .withMasterUrl("https://mymaster.com") .expect()
.build(); .get()
client-cert-data return new DefaultKubernetesClient(config); .withPath("/api/v1/namespaces/test/pods")
Client certi cate data. } .andReturn(200,
} new PodListBuilder()
client-key-data .withNewMetadata()
.withResourceVersion("1")
Client key data.
And inject it on code: .endMetadata()
.withItems(pod1, pod2)
client-key-algorithm
.build())
Client key algorithm. .always();
}
client-key-passphrase }
Client key passphrase.

username
AWS Lambda
Username.
Quarkus integrates with Amazon Lambda.
password
Password
The Cloud Event type that triggers the function is defaultChain . It
./mvnw quarkus:add-extension mvn archetype:generate \
generates a response that triggers a new Cloud Event whose type is
-Dextensions="io.quarkus:quarkus-amazon-lambda" -DarchetypeGroupId=io.quarkus \
defaultChain.output and the event source is defaultChain .
-DarchetypeArtifactId=quarkus-azure-functions-http-archet
ype \
It can be changed by using the next properties:
-DarchetypeVersion={version}
And then implement
com.amazonaws.services.lambda.runtime.RequestHandler interface. quarkus.funqy.knative-events.mapping.defaultChain.trigger=c
onfigChain.output
public class TestLambda Funqy quarkus.funqy.knative-events.mapping.defaultChain.response-
implements RequestHandler<MyInput, MyOutput> { type=annotated
@Override Quarkus Funqy is part of Quarkus’s serverless strategy and aims to quarkus.funqy.knative-events.mapping.defaultChain.response-
public MyInput handleRequest(MyOutput input, provide a portable Java API to write functions deployable to various source=configChain
Context context) { FaaS environments like AWS Lambda, Azure Functions, Knative, and
} Knative events.
}
The properties are of form: quarkus.funqy.knative-events.mapping.
public class GreetingFunction { {function name}. .

The interface @Inject Also can be overriden with


com.amazonaws.services.lambda.runtime.RequestStreamHandler is also GreetingService service; @io.quarkus.funqy.knative.events.CloudEventMapping annotation.
supported.
@io.quarkus.funqy.Funq @Funq
The interface com.amazon.ask.SkillStreamHandler is also supported. public String greet(String name) {} @CloudEventMapping(trigger = "annotated", responseSource =
"annotated", responseType = "lastChainLink")
You can set the handler name by using quarkus.lambda.handler @io.quarkus.funqy.Funq("HelloCustomer") public String annotatedChain(String input) {}
property or by annotating the Lambda with the CDI @Named public String greet(Customer name) {}
annotation.
@Funq
Test public Greeting greet(Friend friend,
responseType chains annotatedChain response to lastChainLink

@io.quarkus.funqy.Context AwsContext ctx) {}


function.
You can write tests for Amazon lambdas:
}
@Funq
<dependency> public void lastChainLink(String input,
<groupId>io.quarkus</groupId> @Context io.quarkus.funqy.knative.events.CloudE
<artifactId>quarkus-test-amazon-lambda</artifactId> In case of Amazon Lambda, only one Funqy function can be
vent event) {}
<scope>test</scope> exported per Amazon Lambda deployment. If there is only one
</dependency> method annotated with @Funq then no prob, if not, you need to set
the function name with quarkus.funqy.export property.
A K-Native Trigger looks like:
Funqy HTTP
@Test apiVersion: eventing.knative.dev/v1alpha1
public void testLambda() { You can invoke on Funqy functions in a pure HTTP environment kind: Trigger
MyInput in = new MyInput(); with simple adding the Funqy HTTP extension. metadata:
in.setGreeting("Hello"); name: defaultchain
in.setName("Stu"); spec:
<dependency>
MyOutput out = LambdaClient.invoke(MyOutput.class, in); filter:
<groupId>io.quarkus</groupId>
} attributes:
<artifactId>quarkus-funqy-http</artifactId>
type: defaultChain
</dependency>
subscriber:
ref:
To scaffold a AWS Lambda run:
apiVersion: serving.knative.dev/v1
Funqy Cloud Events kind: Service
mvn archetype:generate \ name: funqy-knative-events-quickstart
-DarchetypeGroupId=io.quarkus \
Add the extension:
-DarchetypeArtifactId=quarkus-amazon-lambda-archetype \
-DarchetypeVersion={version}
<dependency> And to curl from inside the Kubernetes cluster:
<groupId>io.quarkus</groupId>
<artifactId>quarkus-funqy-knative-events</artifactId>
Azure Functions </dependency>

Quarkus can make a microservice be deployable to the Azure


Functions.
@Funq
To scaffold a deployable microservice to the Azure Functions run: public String defaultChain(String input) {}
curl -v "http://default-broker.knativetutorial.svc.cluster. Apache Camel Possible Swagger UI options with quarkus.swagger-ui pre x:
local" \
urls
-X POST \ Apache Camel Quarkus has its own site:
-H "Ce-Id: 1234" \ https://github.com/apache/camel-quarkus The urls that will be included as options. (ie quarkus.swagger-

-H "Ce-Specversion: 1.0" \ ui.urls.petstore=https://petstore.swagger.io/v2/swagger.json )

-H "Ce-Type: defaultChain" \ WebSockets


-H "Ce-Source: curl" \ urls-primary-name
-H "Content-Type: application/json" \ Quarkus can be used to handling web sockets. If urls option is used, this will be the name of the default
-d '"Start"' selection.
./mvnw quarkus:add-extension
title
-Dextensions="quarkus-websockets"
The html title for the page.

theme
And web sockets classes can be used:
Swagger UI theme to be used.
@ServerEndpoint("/chat/{username}")
footer
@ApplicationScoped
public class ChatSocket { A footer for the html page. Nothing by default.

@OnOpen deep-linking
public void onOpen(Session session, Enables deep linking for tags and operations.
@PathParam("username") String username) {}
display-operation-id
@OnClose
Controls the display of operationId in operations list.
public void onClose(..) {}

default-models-expand-depth
@OnError
public void onError(..., Throwable throwable) {} The default expansion depth for models.

@OnMessage default-model-expand-depth
public void onMessage(...) {} 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.
OpenAPI
display-request-duration
Quarkus can expose its API description as OpenAPI spec and test it Controls the display of the request duration (in milliseconds) for
using Swagger UI. "Try it out" requests.

./mvnw quarkus:add-extension doc-expansion


-Dextensions="io.quarkus:quarkus-smallrye-openapi" Controls the default expansion setting for the operations and
tags.

Then you only need to access to /openapi to get OpenAPI v3 spec filter
of services. Enables ltering.

You can update the OpenApi path by setting quarkus.smallrye-


max-displayed-tags
openapi.path property.
Limits the number of tagged operations displayed to at most this
Also, in case of starting Quarkus application in dev or test mode, many.
Swagger UI is accessible at /swagger-ui . If you want to use it in
production mode you need to set quarkus.swagger-ui.always- operations-sorter
include property to true . Apply a sort to the operation list of each API. ( alpha , method ,
function )
You can update the Swagger UI path by setting quarkus.swagger-
ui.path property. show-extensions
Controls the display of vendor extension.
quarkus.swagger-ui.path=/my-custom-path
show-common-extensions
Controls the display of extensions. presets Add a Security Scheme name to the generated OpenAPI
A list of presets to use in Swagger UI. document. (default: SecurityScheme )
tag-sorter
Apply a sort to the tag list of each API. You can customize the output by using Open API v3 annotations. security-scheme-description
Add a description to the Security Scheme. (default:
on-complete @Schema(name="Developers", Authentication )

Provides a mechanism to be noti ed when Swagger UI has description="POJO that represents a developer.")
nished rendering a newly provided de nition. public class Developer { basic-security-scheme-value
@Schema(required = true, example = "Alex") Add a scheme value to the Basic HTTP Security Scheme.
syntax-highlight private String name; (default: basic )
}
Set to false to deactivate syntax highlighting of payloads and
cURL command. jwt-security-scheme-value
@POST
Add a scheme value to the JWT Security Scheme. (default:
@Path("/developer")
oauth2-redirect-url bearer )
@Operation(summary = "Create deeloper",
OAuth redirect URL. description = "Only be done by admin.")
jwt-bearer-format
public Response createDeveloper(
request-interceptor @RequestBody(description = "Developer object", Add a bearer format to the JWT Security Scheme. (default: JWT )

Function to intercept remote de nition, "Try it out", and OAuth 2.0 required = true,
requests. content = @Content(schema = oidc-open-id-connect-url
@Schema(implementation = Developer.class))) Add a openIdConnectUrl value to the OIDC Security Scheme
request-curl-options Developer developer)

Array of command line options available to the curl command. oauth2-implicit-refresh-url


Add a implicit ow refreshUrl value to the OAuth2 Security
response-interceptor All possible annotations can be seen at Scheme
Function to intercept remote de nition, "Try it out", and OAuth 2.0 org.eclipse.micropro le.openapi.annotations package.
responses. oauth2-implicit-authorization-url
You can also serve OpenAPI Schema from static les instead of
Add an implicit ow authorizationUrl value to the OAuth2 Security
dynamically generated from annotation scanning.
show-mutated-request Scheme
Uses the mutated request returned from a requestInterceptor to You need to put OpenAPIdocumentation under META-INF directory
produce the curl command in the UI. (ie: META-INF/openapi.yaml ). oauth2-implicit-token-url
Add an implicit ow tokenUrl value to the OAuth2 Security
supported-submit-methods A request to /openapi will serve the combined OpenAPI document Scheme
from the static le and the generated from annotations. You can
List of HTTP methods that have the "Try it out" feature enabled.
disable the scanning documents by adding the next con guration
property: mp.openapi.scan.disable=true .
Mail Sender
validator-url
Swagger UI attempts to validate specs against swagger.io’s Other valid document paths are: META-INF/openapi.yml , META- You can send emails by using Quarkus Mailer extension:
online validator. INF/openapi.json , WEB-INF/classes/META-INF/openapi.yml , WEB-
INF/classes/META-INF/openapi.yaml , WEB-INF/classes/META- ./mvnw quarkus:add-extension
with-credentials INF/openapi.json . -Dextensions="io.quarkus:quarkus-mailer"
Enables passing credentials, as de ned in the Fetch standard, in
CORS requests that are sent by the browser. You can store generated OpenAPI schema if quarkus.swagger-
ui.store-schema-directory is set.
You can inject two possible classes io.quarkus.mailer.Mailer for
model-property-macro
Possible OpenAPI options with quarkus.smallrye-openapi pre x: synchronous API or io.quarkus.mailer.reactive.ReactiveMailer for
Function to set default values to each property in model. asynchronous/reactive API.
path
parameter-macro The path at which to register the OpenAPI Servlet. (default: @Inject
Function to set default value to parameters. openapi ) Mailer mailer;

persist-authorization store-schema-directory
It persists authorization data and it would not be lost on browser The generated OpenAPI schema documents will be stored here And then you can use them to send an email:
close/refresh. on build.
mailer.send(
layout security-scheme Mail.withText("to@acme.org", "Subject", "Body")
The name of a component available via the plugin system to use Add a certain SecurityScheme with con g. ( basic , jwt , oidc , );
as the top-level layout for Swagger UI. oauth2Implicit )

plugins security-scheme-name Reactive Mail client


A list of plugin functions to use in Swagger UI.
@Inject Parameter Default Description @Inject
ReactiveMailer reactiveMailer; MockMailbox mailbox;
mailer.password The password.
CompletionStage<Response> stage = @BeforeEach
reactiveMailer.send( void init() {
Mail.withText("to@acme.org", "Subject", "Body") mailer.ssl false Enables SSL. mailbox.clear();
) }
.subscribeAsCompletionStage()
.thenApply(x -> Response.accepted().build());
mailer.trust-all false Trust all certi cates. List<Mail> sent = mailbox
.getMessagesSentTo("to@acme.org");

Max open
mailer.max-pool-size 10
If you are using quarkus-resteasy-mutiny , you can return connections .
io.smallrye.mutiny.Uni type. Scheduled Tasks
Mail class contains methods to add cc , bcc , headers , bounce Hostname for You can schedule periodic tasks with Quarkus.
address , reply to , attachments , inline attachments and html body . mailer.own-host-name HELO/EHLO and
Message-ID
@ApplicationScoped
mailer.send(Mail.withHtml("to@acme.org", "Subject", body) public class CounterBean {
.addInlineAttachment("quarkus.png",
Connection pool
new File("quarkus.png"), mailer.keep-alive true @Scheduled(every="10s", delayed="1s")
enabled.
"image/png", "<my-image@quarkus.io>")); void increment() {}

mailer.disable-esmtp false Disable ESMTP. @Scheduled(cron="0 15 10 * * ?")


If you need deep control you can inject Vert.x mail client void morningTask() {}
@Inject MailClient client;
}
TLS security mode.
You need to con gure SMTP properties to be able to send an email: mailer.start-tls OPTIONAL DISABLED , OPTIONAL ,
REQUIRED .
every and cron parameters can be surrounded with {} and the
quarkus.mailer.from=test@quarkus.io value is used as con g property to get the value.
quarkus.mailer.host=smtp.sendgrid.net
Login mode. NONE , @Scheduled(cron = "{morning.check.cron.expr}")
quarkus.mailer.port=465 mailer.login NONE
OPTIONAL , REQUIRED .
quarkus.mailer.ssl=true void morningTask() {}
quarkus.mailer.username=....
quarkus.mailer.password=.... mailer.auth-methods All methods. Space-separated list.
And con gure the property into application.properties :

List of Mailer parameters. quarkus. as a pre x is skipped in the next mailer.key-store Path of the key store. morning.check.cron.expr=0 15 10 * * ?
table.
mailer.key-store-
Parameter Default Description Key store password. By default Quarkus expresion is used, but you can change that by
password
setting quarkus.scheduler.cron-type property.
mailer.from Default address.
if you enable SSL for the mailer and you want to build a
quarkus.scheduler.cron-type=unix
native executable, you will need to enable the SSL support
Emails not sent, just quarkus.ssl.native=true .
false in prod , true in
mailer.mock printed and stored in
dev and test .
a MockMailbox . Testing org.quartz.Scheduler can be injected as any other bean and
scehdule jobs programmatically.
If is set to true , which is the default value in
quarkus.mailer.mock
mailer.bounce- devand test mode, you can inject MockMailbox to get the sent @Inject
Default address. messages.
address org.quartz.Scheduler quartz;

quartz.scheduleJob(job, trigger);
mailer.host mandatory SMTP host.

mailer.port 25 SMTP port. Kogito


Quarkus integrates with Kogito, a next-generation business
mailer.username The username. automation toolkit from Drools and jBPM projects for adding
business automation capabilities.
To start using it you only need to add the next extension:
try (Git git = Git.cloneRepository() import org.jboss.stm.annotations.ReadLock;
.setDirectory(tmpDir) import org.jboss.stm.annotations.State;
./mvnw quarkus:add-extension .setURI(url) import org.jboss.stm.annotations.WriteLock;
-Dextensions="kogito" .call()) {
return tmpDir.toString(); public class FlightServiceImpl
} implements FlightService {
@State
Apache Tika private int numberOfBookings;

Quarkus integrates with Apache Tika to detect and extract When running in native mode, make sure to con gure SSL @ReadLock
metadata/text from different le types: access correctly quarkus.ssl.native=true (Native and SSL). public int getNumberOfBookings() {
return numberOfBookings;
./mvnw quarkus:add-extension Web Resources }
-Dextensions="quarkus-tika"
You can serve web resources with Quarkus. You need to place web @WriteLock
resources at src/main/resources/META-INF/resources and then they public void makeBooking(String details) {
are accessible (ie http://localhost:8080/index.html) numberOfBookings += 1;
@Inject }
io.quarkus.tika.TikaParser parser; By default static resources as served under the root context. You }
can change this by using quarkus.http.root-path property.
@POST
@Path("/text")
@Consumes({ "text/plain", "application/pdf",
Transactional Memory Any member is saved/restored automatically ( @State is not
"application/vnd.oasis.opendocument.text" }) mandatory). You can use @NotState to avoid behaviour.
Quarkus integrates with the Software Transactional Memory (STM)
@Produces(MediaType.TEXT_PLAIN)
implementation provided by the Narayana project. Transaction boundaries
public String extractText(InputStream stream) {
return parser.parse(stream).getText();
Declarative
} ./mvnw quarkus:add-extension
-Dextensions="narayana-stm"
@NestedTopLevel : De nes that the container will create a new
top-level transaction for each method invocation.
You can con gure Apache Tika in application.properties le by
Transactional objects must be interfaces and annotated with @Nested :De nes that the container will create a new top-level
using next properties pre xed with quarkus :
org.jboss.stm.annotations.Transactional . or nested transaction for each method invocation.
Parameter Default Description
Programmatically
@Transactional
Path to the Tika @NestedTopLevel
tika.tika-config- AtomicAction aa = new AtomicAction();
tika-config.xml con guration public interface FlightService {
path
resource. int getNumberOfBookings();
aa.begin();
void makeBooking(String details);
{
}
CSV of the try {
abbreviated or full flightService.makeBooking("BA123 ...");
quarkus.tika.parsers parser class to be taxiService.makeBooking("East Coast Taxis ...");
The pessimistic strategy is the default one, you can change to
loaded by the
extension. optimistic by using @Optimistic . aa.commit();
} catch (Exception e) {
Then you need to create the object inside org.jboss.stm.Container .
aa.abort();
The document may }
tika.append-embedded- have other embedded Container<FlightService> container = new Container<>(); }
true
content documents. Set if FlightServiceImpl instance = new FlightServiceImpl();
autmatically append. FlightService flightServiceProxy = container.create(instanc
e);
Quartz
JGit Quarkus integrates with Quartz to schedule periodic clustered
The implementation of the service sets the locking and what needs
tasks.
Quarkus integrates with JGit to integrate with Git repositories: to be saved/restored:

./mvnw quarkus:add-extension
./mvnw quarkus:add-extension
-Dextensions="quartz"
-Dextensions="quarkus-jgit"

And then you can start using JGit:


instance-name
@ApplicationScoped <html>
public class TaskBean { The name of the Quartz instance. (default: <head>
QuarkusQuartzScheduler ) <meta charset="UTF-8">
@Transactional <title>Simple Include</title>
@Scheduled(every = "10s") thread-count </head>
void schedule() { The size of scheduler thread pool. (default: 25 ) <body>
Task task = new Task(); {#include foo limit=10 /}
task.persist(); thread-priority </body>
} </html>
Thread priority of worker threads in the pool. (default: 5 )
}

force-start
To render the template:
The scheduler will be started even if no scheduled business
To con gure in clustered mode vida DataSource:
methods are found.
public class Item {
quarkus.datasource.url=jdbc:postgresql://localhost/quarkus_ start-mode public String name;
test public BigDecimal price;
Scheduler can be started in different modes: normal , forced or
quarkus.datasource.driver=org.postgresql.Driver }
halted . (default: normal )
# ...
@Inject
quarkus.quartz.clustered=true Qute io.quarkus.qute.Template item;
quarkus.quartz.store-type=db
Qute is a templating engine designed speci cally to meet the @GET
Quarkus needs. Templates should be placed by default at @Path("{id}")
src/main/resources/templates aand subdirectories. @Produces(MediaType.TEXT_HTML)
You need to de ne the datasource used by clustered mode
public TemplateInstance get(@PathParam("id") Integer id) {
and also import the database tables following the Quartz
./mvnw quarkus:add-extension return item.data("item", service.findItem(id));
schema.
-Dextensions="quarkus-resteasy-qute" }

Quartz can be con gured usinf the following properties with


@TemplateExtension
quarkus.quartz pre x:
static BigDecimal discountedPrice(Item item) {
Templates can be de ned in any format, in case of HTML: return item.price.multiply(new BigDecimal("0.9"));
clustered
item.html }
Enable cluster mode or not.
{@org.acme.Item item} @TemplateExtension(namespace = "str")
store-type <!DOCTYPE html> public static class StringExtensions {
The type of store to use. Possible values: ram , db (default: ram ) <html> static String reverse(String val) {
<head> return new StringBuilder(val).reverse().toString();
datasource <meta charset="UTF-8"> }
<title>{item.name}</title> }
The name of the datasource to use.
</head>
<body>
table-prefix
<h1>{item.name ?: 'Unknown'}</h1>
The pre x for quartz job store tables. (default: QRTZ_ ) If @ResourcePath is not used in Template then the name of the eld is
<h2>{str:reverse('Hello')}</h2>
used as le name. In this case the le should be
<div>Price: {item.price}</div>
src/main/resources/templates/item.{} . Extension of the le is not
trigger-listeners.<name>.class {#if item.price > 100}
required to be set.
Class name for the trigger. <div>Discounted Price: {item.discountedPrice}</div>
{/if} discountedPrice is not a eld of the POJO but a method call.
trigger-listeners.<name>.property-name </body> Method de nition must be annotated with @TemplateExtension and
</html> be static method. First parameter is used to match the base object
The properties passed to the class.
( Item ). @TemplateExtension can be used at class level:
job-listeners.<name>.class

Class name for the job. First line is not mandatory but helps on doing property checks at @TemplateExtension
compilation time. public class MyExtensions {
job-listeners.<name>.property-name static BigDecimal discountedPrice(Item item) {
Including templates passing parameters: return item.price.multiply(new BigDecimal("0.9"));
The properties passed to the class.
}
}
plugins.<name>.class

Class name for the plugin.


Methods with multiple parameters are supported too:
plugins.<name>.property-name
The properties passed to the class
Message Bundling Value resolvers are invoked when evaluating expressions.
{item.discountedPrice(2)}

@io.quarkus.qute.i18n.MessageBundle void configureEngine(@Observes EngineBuilder builder) {


public interface AppMessages { builder.addValueResolver(ValueResolver.builder()
static BigDecimal discountedPrice(Item item, int scale) { @io.quarkus.qute.i18n.Message("Hello {name}!") .appliesTo(ctx -> ctx.getBase() instanceof Long && ct
return item.price.multiply(scale); String hello_name(String name); x.getName().equals("tenTimes"))
} } .resolveSync(ctx -> (Long) ctx.getBase() * 10)
.build());
}

Qute for syntax supports any instance of Iterable , Map.EntrySet , There are 3 methods to inject the message:
Stream or Integer .
MessageBundles.get(AppMessages.class).hello_name("Lucie"); Content Filters
{#for i in total}
{i}:
Content lters can be used to modify the template contents before
{/for}
parsing.
or
void configureEngine(@Observes EngineBuilder builder) {
@Inject AppMessages app; builder.addParserHook(new ParserHook() {
The next map methods are supported:
@Override
app.hello_name("Lucie"); public void beforeParsing(ParserHelper parserHelper)
{#for key in map.keySet} {
{#for value in map.values} parserHelper.addContentFilter(contents -> content
{map.size} s.replace("${", "$\\{"));
or
{#if map.isEmpty} }
{map['foo'] });
<p>{msg:hello_name('Lucie')}</p>
}

The next list methods are supported:


Localization
Reactive and Async
{list[0]} There are two ways to set localized message:
CompletionStage<String> async = report.renderAsync();
Multi<String> publisher = report.createMulti();
@io.quarkus.qute.i18n.Localized("de")
The next number methods are supported: public interface GermanAppMessages {
Uni<String> content = io.smallrye.mutiny.Uni.createFrom()
.completionStage(() -> report.r
{#if counter.mod(5) == 0} @Override
enderAsync());
@io.quarkus.qute.i18n.Message("Hallo {name}!")
String hello_name(String name);
}
Switch/When
Qute Mail Integration

{#switch person.name}
{#case 'John'}
or @Inject
MailTemplate hello;
Hey John! msg_de.properties
{#case 'Mary'}
CompletionStage<Void> c = hello.to("to@acme.org")
Hey Mary! hello_name=Hallo {name}!
.subject("Hello from Qute template")
{/switch}
.data("name", "John")
.send();
You can render programmaticaly the templates too:
{#when items.size}
{#is 1} (1) // file located at src/main/resources/templates/reports/v1/ INFO: Template located at src/main/resources/templates/hello.
There is exactly one item! report_01.{} [html|txt] .
{#is > 10} (2) @ResourcePath("reports/v1/report_01")
There are more than 10 items! Template report;
Sentry
{#else} (3)
There are 2 -10 items! String output = report
Quarkus integrates with Sentry for logging errors into an error
{/when} .data("samples", service.get())
monitoring system.
.render();

./mvnw quarkus:add-extension
Following operators can be used either in when and switch : not, ne, -Dextensions="quarkus-logging-sentry"
!= , gt, > , ge, >= , lt, < , le, <= , in , ni, !in . Value Resolvers
And the con guration to send all errors occuring in the package @ApplicationScoped
quarkus.banner.enabled
org.example to Sentrty with DSN https://abcd@sentry.io/1234 : Enables banner. (default : true )
public class CachedBean {

quarkus.log.sentry=true @CacheResult(cacheName = "foo") OptaPlanner


quarkus.log.sentry.dsn=https://abcd@sentry.io/1234 public Object load(Object key) {}
quarkus.log.sentry.level=ERROR
Quarkus integrates with OptaPlanner.
quarkus.log.sentry.in-app-packages=org.example @CacheInvalidate(cacheName = "foo")
public void invalidate(Object key) {}
./mvnw quarkus:add-extension
-Dextensions="quarkus-optaplanner, quarkus-optaplanner-ja
Full list of con guration properties having quarkus.log as pre x: @CacheInvalidateAll(cacheName = "foo")
ckson"
public void invalidateAll() {}
sentry.enable }

Enable the Sentry logging extension (default: false)


@PlanningSolution
sentry.dsn You can disable the caching system by setting public class TimeTable {
Where to send events. quarkus.cache.enabled property to false . }

This extension uses Caffeine as its underlying caching provider. @Inject


sentry.level
private SolverManager<TimeTable, UUID> solverManager;
Log level (default: WARN ) Each cache can be con gured individually:
UUID problemId = UUID.randomUUID();
sentry.server-name quarkus.cache.caffeine."foo".initial-capacity=10 SolverJob<TimeTable, UUID> solverJob = solverManager.solve
Sets the server name that will be sent with each event. quarkus.cache.caffeine."foo".maximum-size=20 (problemId, problem);
quarkus.cache.caffeine."foo".expire-after-write TimeTable solution = solverJob.getFinalBestSolution();
sentry.in-app-packages quarkus.cache.caffeine."bar".maximum-size=1000

Con gure which package pre xes your application uses.


Possible con guration options pre xed with quarkus.optaplanner :

JSch Full list of con guration properties having quarkus.cache.caffeine.


[cache-name] as pre x: solver-config-xml

Quarkus integrates with Jsch for SSH communication. A classpath resource to read the solver con guration XML. Not
initial-capacity mandatory.
Minimum total size for the internal data structures.
./mvnw quarkus:add-extension
solver.environment-mode
-Dextensions="quarkus-jsch"
maximum-size Enable runtime assertions to detect common bugs in your
Maximum number of entries the cache may contain. implementation during development. Possible values:
FAST_ASSERT , FULL_ASSERT , NON_INTRUSIVE_FULL_ASSERT ,
JSch jsch = new JSch(); expire-after-write NON_REPRODUCIBLE , REPRODUCIBLE . (default: REPRODUCIBLE )
Session session = jsch.getSession(null, host, port); Speci es that each entry should be automatically removed from
session.setConfig("StrictHostKeyChecking", "no"); the cache once a xed duration has elapsed after the entry’s solver.move-thread-count
session.connect(); creation, or last write. Enable multithreaded solving for a single problem. Possible
values: MOVE_THREAD_COUNT_NONE , MOVE_THREAD_COUNT_AUTO , a number
expire-after-access or formula based on the available processors. (default:
MOVE_THREAD_COUNT_NONE )
Cache Speci es that each entry should be automatically removed from
the cache once a xed duration has elapsed after the entry’s
Quarkus can cache method calls by using as key the tuple (method creation, or last write. solver.termination.spent-limit

+ arguments). How long the solver can run. (ie 5s )

You can multiple cache annotations on a single method.


solver.termination.unimproved-spent-limit
./mvnw quarkus:add-extension
-Dextensions="cache" How long the solver can run without nding a new best solution
If you see a javax.enterprise.context.ContextNotActiveException , after nding a new best solution. (ie 2h )
you need to add the quarkus-smallrye-context-propagation
extension. solver.termination.best-score-limit
@io.quarkus.cache.CacheResult(cacheName = "weather-cache")
Terminates the solver when a speci c or higher score has been
public String getDailyForecast(LocalDate date, String city) Banner reached. (ie 0hard/-1000soft )
{}
Banner is printed by default. It is not an extension but placed in the solver-manager.parallel-solver-count
core.
The number ofsolvers that run in parallel. (default:
@CacheInvalidate removes the element represented by the PARALLEL_SOLVER_COUNT_AUTO )
quarkus.banner.path
calculated cache key from cache. @CacheInvalidateAll removes all
entries from the cache. @CacheKey to speci cally set the arguments Path is relative to root of the classpath. (default:
b d k d f ll ) Context Propagation
Keys whose value is a raw string. The keys that end up in the user To change how you can refer to webjars skipping the version part
./mvnw quarkus:add-extension
con guration are the keys speci ed her with '/' replaced by '.' you can use WebJars locator extension.
-Dextensions="quarkus-smallrye-context-propagation"

properties-value-keys ./mvnw quarkus:add-extension


Keys whose value represents a properties-like le conttent. -Dextensions="webjars-locator"
If using mutiny extension together you already get context
propagation for ArC, RESTEasy and transactions. With
fail-on-missing-key
CompletionStage you need to:
If the application will not start if any of the con gured con g Then the JavaScript location is changed from
sources cannot be located. (default: true ) /webjars/jquery/3.1.1/jquery.min.js to
@Inject ThreadContext threadContext;
@Inject ManagedExecutor managedExecutor;
/webjars/jquery/jquery.min.js in your HTML les.
trust-store

threadContext.withContextCapture(..) TrustStore to be used containing the SSL certi cate used by Amazon SES
.thenApplyAsync(r -> {}, managedExecutor); Consul agent.
mvn quarkus:add-extension
trust-store-password -Dextensions="amazon-ses"
If you are going to use security in a reactive environment you will Password of TrustStore to be used containing the SSL certi cate
likely need Smallrye Content Propagation to propagate the identity used by Consul agent.
throughout the reactive callback.
key-password @Inject

Con guration from HasiCorp Consul Password to recover key from KeyStore for SSL client
software.amazon.awssdk.services.ses.SesClient sesClient;

authentication with Consul agent.


@Inject
You can read runtime con guration from HashiCorp Consul.
software.amazon.awssdk.services.ses.SesAsyncClient sesClien
agent.host-port
t;
./mvnw quarkus:add-extension Consul agent host. (default: localhost:8500 )
-Dextensions="consul-config"
agent.use-https

Use HTTPS when communicating with the agent. (default: false )


quarkus.ses.endpoint-override=http://localhost:8012
quarkus.ses.aws.region=us-east-1
You need to con gure Consul:
quarkus.ses.aws.credentials.type=static
agent.token
quarkus.ses.aws.credentials.static-provider.access-key-id=t
quarkus.consul-config.enabled=true Consul token to be provided when authentication is enabled. est-key
quarkus.consul-config.agent.host-port=localhost:8500 quarkus.ses.aws.credentials.static-provider.secret-access-k
quarkus.consul-config.properties-value-keys=config/consul-t agent.key-store ey=test-secret
est KeyStore (classpath or lesystem) to be used containing the SSL
certi cate used by Consul agent.
You need to set a HTTP client either URL Connection :
agent.key-store-password
@ConfigProperty(name = "greeting.message")
String message; Password of KeyStore. <dependency>
<groupId>software.amazon.awssdk</groupId>
agent.trust-certs <artifactId>url-connection-client</artifactId>
In Consul: To trust all certi cates or not. </dependency>

agent.connection-timeout
"Key": "config/consul-test",
"Value": "greeting.message=Hello from Consul" Connection timeout. (default: 10S ) or Apache HTTP:

agent.read-timeout <dependency>
Possible con guration parameters, pre xed with quarkus.consul- Reading timeout. (default: 60S ) <groupId>software.amazon.awssdk</groupId>
config : <artifactId>apache-client</artifactId>
Amazon Alexa </dependency>
enabled

The application will attempt to look up the con guration from You can use Amazon Alexa by adding the extension:
Consul. (default: false )
quarkus.ses.sync-client.type=apache
./mvnw quarkus:add-extension
prefix -Dextensions="quarkus-amazon-alexa"
Common pre x that all keys share when looking up the keys from
Or async:
Consul. The pre x is not included in the keys of the user
con guration
WebJar Locator
raw-value-keys
<dependency> Spring DI Spring Boot Con guration
<groupId>software.amazon.awssdk</groupId>
<artifactId>netty-nio-client</artifactId> Quarkus provides a compatibility layer for Spring dependency Quarkus provides a compatibility layer for Spring Boot
</dependency> injection. ConfigurationProperties .

./mvnw quarkus:add-extension ./mvnw quarkus:add-extension


Con guration properties are the same as Amazon DynamoDB but -Dextensions="quarkus-spring-di" -Dextensions="quarkus-spring-boot-properties"
changing the pre x from dynamodb to ses .

Jbang Some examples of what you can do. Notice that annotations are
@ConfigurationProperties("example")
the Spring original ones.
public final class ClassProperties {
Creating an initial script:
@Configuration
private String value;
public class AppConfiguration {
jbang scripting/quarkusapp.java private AnotherClass anotherClass;

@Bean(name = "capitalizeFunction")
// getters/setters
public StringFunction capitalizer() {
Adding Quarkus dependencies in script: }
return String::toUpperCase;
}
//DEPS io.quarkus:quarkus-resteasy:{quarkus-version} }
example.value=class-value
example.anotherClass.value=true
Put some Quarkus CLI code: Or as a component:

@Component("noopFunction")
@Path("/hello")
public class NoOpSingleStringFunction Spring Cloud Con g Client
@ApplicationScoped
implements StringFunction {
public class quarkusapp {
} Quarkus integrates Spring Cloud Con g Client and MicroPro le
@GET
Con g spec.
public String sayHello() {
return "hello";
./mvnw quarkus:add-extension
} Also as a service and injection properties from
-Dextensions="quarkus-spring-cloud-config-client"
public static void main(String[] args) { application.properties .
Quarkus.run(args);
} @Service
} public class MessageProducer { You need to con gure the extension:

@Value("${greeting.message}") quarkus.spring-cloud-config.uri=http://localhost:8089
To run the script: String message; quarkus.spring-cloud-config.username=user
quarkus.spring-cloud-config.password=pass
} quarkus.spring-cloud-config.enabled=true
jbang quarkusapp.java

And you can inject using Autowired or constructor in a component


A Maven goal is provided to scaffold a project: @ConfigProperty(name = "greeting.message")
and in a JAX-RS resource too.
String greeting;
mvn io.quarkus:quarkus-maven-plugin:<version>:create-jbang
@Component
public class GreeterBean {
Pre x is quarkus.spring-cloud-config .

private final MessageProducer messageProducer;


uri

@Autowired @Qualifier("noopFunction") Base URI where the Spring Cloud Con g Server is available.
StringFunction noopStringFunction; (default: localhost:8888 )

public GreeterBean(MessageProducer messageProducer) { username


this.messageProducer = messageProducer; 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 The next return types are supported:
@Query("select m from Movie m where m.rating = ?1")
Enables read con guration from Spring Cloud Con g Server. org.springframework.http.ResponseEntity and java.util.Map .
Iterator<Movie> findByRating(String rating);
(default: false )
The next parameter types are supported: An Exception argument
@Modifying
and ServletRequest / HttpServletRequest (adding quarkus-undertow
fail-fast @Query("delete from Movie where rating = :rating")
dependency).
True to not start application if cannot access to the server. void deleteByRating(@Param("rating") String rating);
(default: false ) Spring Data JPA @Query(value = "SELECT COUNT(*), publicationYear FROM Book
connection-timeout GROUP BY publicationYear")
While users are encouraged to use Hibernate ORM with Panache List<BookCountByYear> findAllByPublicationYear2();
The amount of time to wait when initially establishing a for Relational Database access, Quarkus provides a compatibility
connection before giving up and timing out. (default: 10S ) layer for Spring Data JPA repositories. interface BookCountByYear {
int getPublicationYear();
read-timeout
./mvnw quarkus:add-extension
The amount of time to wait for a read on a socket before an -Dextensions="quarkus-spring-data-jpa" Long getCount();
exception is thrown. (default: 60S ) }

label
INFO: Of course you still need to add the JDBC driver, and con gure
The label to be used to pull remote con guration properties. it in application.properties . What is currently unsupported:

Spring Web public interface FruitRepository


Methods of
org.springframework.data.repository.query.QueryByExampleExec
extends CrudRepository<Fruit, Long> {
utor
Quarkus provides a compatibility layer for Spring Web. List<Fruit> findByColor(String color);
}
QueryDSL support
./mvnw quarkus:add-extension
-Dextensions="quarkus-spring-web" Customizing the base repository
And then you can inject it either as shown in Spring DI or in Spring
Web. java.util.concurrent.Future as return type
Speci cally supports the REST related features. Notice that Native and named queries when using
infrastructure things like BeanPostProcessor will not be executed. Interfaces supported: @Query

org.springframework.data.repository.Repository Spring Data Rest


@RestController
@RequestMapping("/greeting") org.springframework.data.repository.CrudRepository While users are encouraged to use REST Data with Panache for the
public class GreetingController { REST data access endpoints generation, Quarkus provides a
org.springframework.data.repository.PagingAndSortingReposito
compatibility layer for Spring Data REST in the form of the spring-
private final GreetingBean greetingBean; ry
data-rest extension.

public GreetingController(GreetingBean greetingBean) { org.springframework.data.jpa.repository.JpaRepository .


./mvnw quarkus:add-extension
this.greetingBean = greetingBean;
}
INFO: Generated repositories are automatically annotated with -Dextensions="spring-data-rest"
@Transactional .

@GetMapping("/{name}")
Repository fragments is also supported:
public Greeting hello(@PathVariable(name = "name")
import java.util.Optional;
String name) {
public interface PersonRepository import org.springframework.data.repository.CrudRepository;
return new Greeting(greetingBean.greet(name));
extends JpaRepository<Person, Long>, PersonFragment { import org.springframework.data.rest.core.annotation.Reposi
}
toryRestResource;
}
void makeNameUpperCase(Person person); import org.springframework.data.rest.core.annotation.RestRe
} source;

Supported annotations are: RestController , RequestMapping , @RepositoryRestResource(exported = false, path = "/my-fruit


GetMapping , PostMapping , PutMapping , DeleteMapping , PatchMapping , s")
RequestParam , RequestHeader , MatrixVariable , PathVariable , User de ned queries: public interface FruitsRepository extends CrudRepository<Fr
CookieValue , RequestBody , ResponseStatus , ExceptionHandler and uit, Long> {
RestControllerAdvice . @RestResource(exported = true)
Optional<Fruit> findById(Long id);
If you scaffold the project with spring-web extension, then @RestResource(exported = true)
Spring Web annotations are sed in the generated project. Iterable<Fruit> findAll();
mvn io.quarkus:quarkus-maven-plugin:1.13.0.Final:create … - }
Dextensions="spring-web" .
The spring-data-jpa extension will generate an implementation for Checks if the current logged in user is the same as the
@org.springframework.scheduling.annotation.Scheduled(cron=
this repository. Then the spring-data-rest extension will generate a username method parameter:
"*/5 * * * * ?")
REST CRUD resource for it.
void cronJob() {
@PreAuthorize("#person.name == authentication.principal.use System.out.println("Cron expression hardcoded");
The following interfaces are supported:
rname") }
public void doSomethingElse(Person person){}
org.springframework.data.repository.CrudRepository
@Scheduled(fixedRate = 1000)
org.springframework.data.repository.PagingAndSortingReposito @Scheduled(cron = "{cron.expr}")
ry Checks if calling a method if user can access:
org.springframework.data.jpa.repository.JpaRepository
@PreAuthorize("@personChecker.check(#person, authenticatio
n.principal.username)")
Spring Security public void doSomething(Person person){}

Quarkus provides a compatibility layer for Spring Security. @Component


public class PersonChecker {
./mvnw quarkus:add-extension public boolean check(Person person, String username) {
-Dextensions="spring-security" return person.getName().equals(username);
}
}

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. Combining expressions:

Then you can use Spring Security annotations to protect the


@PreAuthorize("hasAnyRole('user', 'admin') AND #user == pri
methods:
ncipal.username")
public void allowedForUser(String user) {}
@Secured("admin")
@GetMapping
public String hello() {
return "hello"; Spring Cache
}
Quarkus provides a compatibility layer for Spring dependency
injection.
Quarkus provides support for some of the most used features of
Spring Security’s @PreAuthorize annotation. ./mvnw quarkus:add-extension
-Dextensions="spring-cache"
Some examples:

hasRole
@org.springframework.cache.annotation.Cacheable("someCache"
@PreAuthorize("hasRole('admin')") )
public Greeting greet(String name) {}
@PreAuthorize("hasRole(@roles.USER)") where roles is a bean
de ned with @Component annotation and USER is a public eld
of the class.
Quarkus provides compatibility with the following Spring Cache
hasAnyRole annotations:

@PreAuthorize("hasAnyRole(@roles.USER, 'view')") @Cacheable

Permit and Deny All @CachePut

@PreAuthorize("permitAll()") @CacheEvict

@PreAuthorize("denyAll()") Spring Schedule


Anonymous and Authenticated Quarkus provides a compatibility layer for Spring Scheduled
annotation.
@PreAuthorize("isAnonymous()")

@PreAuthorize("isAuthenticated()") ./mvnw quarkus:add-extension


-Dextensions="spring-scheduled"
Resources Authors : 1.13.0.Final

https://quarkus.io/guides/ @alexsotob
Java Champion and Director of DevExp at Red Hat
https://www.youtube.com/user/lordofthejars

You might also like