100% found this document useful (2 votes)
1K views

Quarkus Cheat-Sheet: What Is Quarkus? Command Mode

Quarkus is a Kubernetes native Java stack optimized for GraalVM and OpenJDK HotSpot. It uses best-of-breed Java libraries and standards. Quarkus focuses on developer experience and live coding with little configuration. The document provides a cheat sheet on getting started with Quarkus including creating a simple project with Maven or Gradle, packaging options, running in dev mode, and using command line interfaces.

Uploaded by

asrori
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
100% found this document useful (2 votes)
1K views

Quarkus Cheat-Sheet: What Is Quarkus? Command Mode

Quarkus is a Kubernetes native Java stack optimized for GraalVM and OpenJDK HotSpot. It uses best-of-breed Java libraries and standards. Quarkus focuses on developer experience and live coding with little configuration. The document provides a cheat sheet on getting started with Quarkus including creating a simple project with Maven or Gradle, packaging options, running in dev mode, and using command line interfaces.

Uploaded by

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

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.10.2.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.10.2.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 lib }
@Path("/hello")
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() { If quarkus.package.type property is set to fast-jar then Quarkus Use @QuarkusMain in only one place.
return "hello"; brings a JAR with faster startup times.
}
application.properties Use Quarkus.waitForExit() from the main thread if you want to run
}
some logic on startup, and then run like a normal application (i.e.
quarkus.package.uber-jar=true not exit).
quarkus.package.type=fast-jar
Gradle 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 To compile to native, you need to set GRAALVM_HOME environment
do: variable and run the native pro le. @CommandLineArguments
String[] args;

plugins { mvn clean package -Pnative


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

AppCDS
dependencies {
implementation enforcedPlatform('io.quarkus:quarkus-bo Automatically generate AppCDS as part of the build process set the
m:0.26.1') next property: quarkus.package.create-appcds=true .
implementation 'io.quarkus:quarkus-resteasy'
} 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
Adding Con guration Parameters
etValue().toString());
}
To add con guration to your application, Quarkus relies on
}
MicroPro le Con g spec.
All classes annotated with picocli.CommandLine.Command are
registered as CDI beans.
@ConfigProperty(name = "greetings.message")
String message;
If only one class annotated with picocli.CommandLine.Command it will
be used as entry point. If you want to provide your own
Extensions
@ConfigProperty(name = "greetings.message",
@QuarkusMain :
Quarkus comes with extensions to integrate with some libraries defaultValue = "Hello")
such as JSON-B, Camel or MicroPro le spec. To list all available String messageWithDefault;
@QuarkusMain extensions just run:
@CommandLine.Command(name = "demo", mixinStandardHelpOption
@ConfigProperty(name = "greetings.message")
s = true)
./mvnw quarkus:list-extensions Optional<String> optionalMessage;
public class ExampleApp implements Runnable, QuarkusApplica
tion {

@Inject You can use -DsearchPattern=panache to lter out all Properties can be set (in decreasing priority) as:
CommandLine.IFactory factory; extensions except the ones matching the expression.
System properties ( -Dgreetings.message ).
@Override And to register the extensions into build tool:
Environment variables ( GREETINGS_MESSAGE ).
public void run() {
}
./mvnw quarkus:add-extension -Dextensions="" Environment le named .env placed in the current working

directory ( GREETING_MESSAGE= ).
@Override
./mvnw quarkus:remove-extension -Dextensions=""
public int run(String... args) throws Exception { External con g directory under the current working directory:
return new CommandLine(this, factory).execute(arg config/application.properties .
s);
} extensions property supports CSV format to register more Resources src/main/resources/application.properties .
} than one extension at once.
greetings.message = Hello World
Application Lifecycle
Use quarkus.picocli.native-image.processing.enable to false to use
the picocli-codegen annotation processor instead of build steps. You can be noti ed when the application starts/stops by observing
Array , List and Set are supported. The delimiter is comma
StartupEvent and ShutdownEvent events.
You can also con gure CDI beans with PicoCLI arguments: ( , ) char and \ is the escape char.

@ApplicationScoped Con guration Pro les


public class ApplicationLifecycle {
void onStart(@Observes StartupEvent event) {} Quarkus allow you to have multiple con guration in the same le
void onStop(@Observes ShutdownEvent event) {} ( application.properties ).
}
The syntax for this is %{profile}.config.key=value .

Quarkus supports graceful shutdown. By default there is no timeout quarkus.http.port=9090


but can be set by using the quarkus.shutdown.timeout con g %dev.quarkus.http.port=8181
HTTP port will be 9090, unless the 'dev' pro le is active. @io.quarkus.arc.config.ConfigIgnore annotation can be used to
@ConfigProperties(prefix = "greeting", namingStrategy=Namin
ignore the injection of con guration elements.
gStrategy.KEBAB_CASE)
Default pro les are:
public class GreetingConfiguration {
private String message; @ConfigIgnore
dev : Activated when in development mode ( quarkus:dev ).
// getter/setter public Integer ignored;
test : Activated when running tests. }

prod : The default pro le when not running in development or YAML Con g
test mode
This class maps greeting.message property de ned in
application.properties . YAML con guration is also supported. The con guration le is
You can create custom pro le names by enabling the pro le either called application.yaml and you need to register a dependency to
setting quarkus.profile system property or QUARKUS_PROFILE enable its support:
You can inject this class by using CDI @Inject GreetingConfiguration
environment variable. greeting; .
pom.xml

quarkus.http.port=9090 Also you can use an interface approach: <dependency>


%staging.quarkus.http.port=9999 <groupId>io.quarkus</groupId>
@ConfigProperties(prefix = "greeting", namingStrategy=Namin <artifactId>quarkus-config-yaml</artifactId>
gStrategy.KEBAB_CASE) </dependency>
And enable it quarkus.profile=staging . public interface GreetingConfiguration {

To get the active pro le programmatically
use @ConfigProperty(name = "message")
String message(); quarkus:
io.quarkus.runtime.configuration.ProfileManager.getActiveProfile() .
String getSuffix(); datasource:
url: jdbc:postgresql://localhost:5432/some-database
You can also set it in the build tool:
driver: org.postgresql.Driver

<groupId>org.apache.maven.plugins</groupId> If property does not follow getter/setter naming convention you


<artifactId>maven-surefire-plugin</artifactId> need to use org.eclipse.microprofile.config.inject.ConfigProperty
<version>${surefire-plugin.version}</version> to set it. Or with pro les:
<configuration>
<systemPropertyVariables>
Nested objects are also supporte: "%dev":
<quarkus.test.profile>foo</quarkus.test.profile> quarkus:
<buildDirectory>${project.build.directory} @ConfigProperties(prefix = "greeting", namingStrategy=Namin datasource:
</buildDirectory> gStrategy.KEBAB_CASE) url: jdbc:postgresql://localhost:5432/some-database
</systemPropertyVariables> public class GreetingConfiguration { driver: org.postgresql.Driver
</configuration> public String message;
public HiddenConfig hidden;

In case of subkeys ~ is used to refer to the unpre xed part.
public static class HiddenConfig {
Same for maven-failsafe-plugin . public List<String> recipients;
} quarkus:
} http:
test { cors:
useJUnitPlatform() ~: true
systemProperty "quarkus.test.profile", "foo" methods: GET,PUT,POST
}
And an application.properties mapping previous class:

greeting.message = hello
Is equivalent to:
greeting.hidden.recipients=Jane,John
Special properties are set in prod mode:
quarkus.application.version and quarkus.application.name to get quarkus.http.cors=true
them available at runtime. quarkus.http.cors.methods=GET,PUT,POST
Bean Validation is also supported so properties are validated at
startup time, for example @Size(min = 20) public String message; .
@ConfigProperty(name = "quarkus.application.name")
String applicationName; Custom Loader
prefix attribute is not mandatory. If not provided, attribute
is determined by class name (ie GreeetingConfiguration is
translated to greeting or GreetingExtraConfiguration to You can implement your own ConfigSource to load con guration
@Con gProperties from different places than the default ones provided by Quarkus.
greeting-extra ). The su x of the class is always removed.
For example, database, custom XML, REST Endpoints, …
As an alternative to injecting multiple related con guration values, Naming strategy can be changed with property namingStrategy .
you can also use the @io.quarkus.arc.config.ConfigProperties You need to create a new class and implement ConfigSource
KEBAB_CASE (whatever.foo-bar) or VERBATIM (whatever.fooBar).
annotation to group properties. interface:
Then you need to register the Converter as Java service. Create a Quali ers
package com.acme.config;
le with the following content:
public class InMemoryConfig implements ConfigSource {
You can use quali ers to return different implementations of the
/META-INF/services/org.eclipse.microprofile.config.spi.Converter
same interface or to customize the con guration of the bean.
private Map<String, String> prop = new HashMap<>();
com.acme.config.CustomInstantConverter
public InMemoryConfig() { @Qualifier
// Init properties @Retention(RUNTIME)
} @Target({TYPE, METHOD, FIELD, PARAMETER})

Undertow Properties public @interface Quote {
@Override @Nonbinding String value();
public int getOrdinal() { Possible parameters with pre x quarkus.servlet : }
// The highest ordinal takes precedence
context-path @Produces
return 900;
} The context path to serve all Servlet context from. (default: / ) @Quote("")
Message message(InjectionPoint msg) {
@Override default-charset Message m = new Message();
m.setMsn(
public Map<String, String> getProperties() { The default charset to use for reading and writing requests.
msg.getAnnotated()
return prop; (default: UTF-8 )
} .getAnnotation(Quote.class)
.value()

@Override
Injection );
public String getValue(String propertyName) {
return prop.get(propertyName);
Quarkus is based on CDI 2.0 to implement injection of code. It is return m;
}
not fully supported and only a subset of the speci cation is }

implemented.
@Override @Inject
public String getName() { @ApplicationScoped @Quote("Aloha Beach")
return "MemoryConfigSource"; public class GreetingService { Message message;
}
} public String message(String message) {
return message.toUpperCase();
Quarkus breaks the CDI spec by allowing you to inject
}
quali ed beans without using @Inject annotation.
}
Then you need to register the ConfigSource as Java service. Create
a le with the following content: @Quote("Aloha Beach")
Message message;
/META-INF/services/org.eclipse.microprofile.config.spi.ConfigSource
Scope annotation is mandatory to make the bean discoverable.
com.acme.config.InMemoryConfig
@Inject
Quarkus breaks the CDI spec by skipping the @Produces
GreetingService greetingService;
annotation completely if the producer method is annotated
Custom Converters with a scope annotation, a stereotype or a quali er.

You can implement your own conversion types from String. Quarkus is designed with Substrate VM in mind. For this @Quote("")
Implement org.eclipse.microprofile.config.spi.Converter reason, we encourage you to use package-private scope Message message(InjectionPoint msg) {
interface: instead of private. }

@Priority(DEFAULT_QUARKUS_CONVERTER_PRIORITY + 100) Produces @Quote("Aloha Beach")
public class CustomInstantConverter Message message;
implements Converter<Instant> { You can also create a factory of an object by using
@javax.enterprise.inject.Produces annotation.
@Override
Alternatives
public Instant convert(String value) { @Produces
if ("now".equals(value.trim())) { @ApplicationScoped It is also possible to select alternatives for an application using
return Instant.now(); Message message() { application.properties .
} Message m = new Message();
return Instant.parse(value); m.setMsn("Hello");
quarkus.arc.selected-alternatives=org.acme.Foo,org.acme.*,B
} return m;
ar
} }

@Inject
Message msg; Beans by Quarkus Pro le
@Priority annotation is used to override the default
InstantConverter .
Using @io.quarkus.arc.profile.IfBuildProfile and By default the class is in write mode (so no concurrent calls
@ApplicationScoped
@io.quarkus.arc.profile.UnlessBuildProfile annotations, you can allowed) except when lock type is READ where the method can be public class CustomObjectMapperConfig {
conditionally enable a bean. called concurrently if no write operation in process.
@Singleton
@Produces
@Dependent JSON Marshalling/Unmarshalling public ObjectMapper objectMapper() {
public class TracerConfiguration { ObjectMapper objectMapper = new ObjectMapper();
@Produces To work with JSON-B you need to add a dependency: // perform configuration
@IfBuildProfile("prod") return objectMapper;
public Tracer realTracer(Reporter reporter, Configurati ./mvnw quarkus:add-extension }
on configuration) { -Dextensions="io.quarkus:quarkus-resteasy-jsonb" }
return new RealTracer(reporter, configuration);
}
@Produces
@DefaultBean Any POJO is marshaled/unmarshalled automatically.
Default media type in Quarkus RestEasy is JSON.
public Tracer noopTracer() {
return new NoopTracer(); public class Sauce {
} private String name; XML Marshalling/Unmarshalling
} private long scovilleHeatUnits;

To work with JAX-B you need to add a dependency:
// getter/setters
}
Using @io.quarkus.arc.profile.IfBuildProperty annotation, you can ./mvnw quarkus:add-extension
conditionally enable a bean. @io.quarkus.arc.DefaultBean sets the -Dextensions="quarkus-resteasy-jaxb"
default bean.
JSON equivalent:
@Dependent
Then annotated POJOs are converted to XML.
public class TracerConfiguration { {
@Produces "name":"Blair's Ultra Death",
@IfBuildProperty(name = "some.tracer.enabled", stringVa "scovilleHeatUnits": 1100000 @XmlRootElement
lue = "true") } public class Message {
public Tracer realTracer(Reporter reporter, Configurati }
on configuration) {}
@GET
In a POST endpoint example: @Produces(MediaType.APPLICATION_XML)
@Produces
@DefaultBean public Message hello() {
public Tracer noopTracer() {} @POST return message;
} @Consumes(MediaType.APPLICATION_JSON) }
public Response create(Sauce sauce) {
// Create Sauce
return Response.created(URI.create(sauce.getId()))
Properties set at runtime have absolutely no effect on the .build(); JAXP
bean resolution using @IfBuildProperty . }
To work with JAX-P you need to add a dependency:
Container-managed Concurrency
./mvnw quarkus:add-extension
To work with Jackson you need to add:
Quarkus provides @io.quarkus.arc.Lock and a built-in interceptor for -Dextensions="jaxp"
concurrency control.
./mvnw quarkus:add-extension
-Dextensions="quarkus-resteasy-jackson"
@Lock
final DocumentBuilder dBuilder = DocumentBuilderFactory.new
@ApplicationScoped
Instance().newDocumentBuilder();
class SharedService {
If you don’t want to use the default ObjectMapper you can customize final Document doc = dBuilder.parse(in);

it by: return doc.getDocumentElement().getTextContent();
void addAmount(BigDecimal amout) {
}

@Lock(value = Lock.Type.READ, time = 1, unit = TimeUni Validator
t.SECONDS)
BigDecimal getAmount() {
Quarkus uses Hibernate Validator to validate input/output of REST
}
services and business services using Bean validation spec.
}

./mvnw quarkus:add-extension
-Dextensions="io.quarkus:quarkus-hibernate-validator"
Annotate POJO objects with validator annotations such as: You can con gure how Quarkus logs:
@NotExpired
@NotNull , @Digits , @NotBlank , @Min , @Max , …
@JsonbDateFormat(value = "yyyy-MM-dd")
private LocalDate expired; quarkus.log.console.enable=true
public class Sauce { quarkus.log.console.level=DEBUG
quarkus.log.console.color=false
@NotBlank(message = "Name may not be blank") quarkus.log.category."com.lordofthejars".level=DEBUG
private String name;
Manual Validation
@Min(0)
You can call the validation process manually instead of relaying to
private long scovilleHeatUnits;
@Valid by injecting Validator class. Pre x is quarkus.log .

// getter/setters category."<category-name>".level
} @Inject
Validator validator; Minimum level category (default: INFO )

level
To validate an object use @Valid annotation: Default minimum level (default: INFO )
And use it:
public Response create(@Valid Sauce sauce) {} console.enabled
Set<ConstraintViolation<Sauce>> violations =
validator.validate(sauce); Console logging enabled (default: true )

If a validation error is triggered, a violation report is console.format


generated and serialized as JSON. If you want to Format pattern to use for logging. Default value:
manipulate the output, you need to catch in the code the Localization
%d{yyyy-MM-dd HH:mm:ss,SSS} %-5p [%c{3.}] (%t) %s%e%n
ConstraintViolationException exception.
You can con gure the based locale for validation messages.
console.level
Create Your Custom Constraints
quarkus.default-locale=ca-ES Minimum log level (default: INFO )
First you need to create the custom annotation: # Supported locales resolved by Accept-Language
quarkus.locales=en-US,es-ES,fr-FR, ca_ES console.color

@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, Allow color rendering (default: true )
PARAMETER, TYPE_USE })
ValidationMessages_ca_ES.properties file.enable
@Retention(RUNTIME)
@Documented
pattern.message=No conforme al patro File logging enabled (default: false )
@Constraint(validatedBy = { NotExpiredValidator.class})
public @interface NotExpired { file.format

Format pattern to use for logging. Default value:
String message() default "Sauce must not be expired"; @Pattern(regexp = "A.*", message = "{pattern.message}") %d{yyyy-MM-dd HH:mm:ss,SSS} %h %N[%i] %-5p [%c{3.}] (%t) %s%e%n
Class<?>[] groups() default { }; private String name;
Class<? extends Payload>[] payload() default { };
file.level

} Minimum log level (default: ALL )
Bean Validation can be con gured . The pre x is:
quarkus.hibernate-validator . file.path

You need to implement the validator logic in a class that fail-fast


The path to log le (default: quarkus.log )
implements ConstraintValidator . When fail fast is enabled the validation will stop on the rst
file.rotation.max-file-size
constraint violation detected. (default: false )
public class NotExpiredValidator The maximum le size of the log le
implements ConstraintValidator<NotExpired, LocalDate> method-validation.allow-overriding-parameter-constraints
{ file.rotation.max-backup-index
De ne whether overriding methods that override constraints
The maximum number of backups to keep (default: 1 )
should throw an exception. (default: false ).
@Override
public boolean isValid(LocalDate value, file.rotation.file-suffix
method-validation.allow-parameter-constraints-on-parallel-methods
ConstraintValidatorContext ctx) {
if ( value == null ) return true; De ne whether parallel methods that de ne constraints should Rotating log le su x.
LocalDate today = LocalDate.now(); throw an exception. (default: false ).
file.rotation.rotate-on-boot
return ChronoUnit.YEARS.between(today, value) > 0;
} method-validation.allow-multiple-cascaded-validation-on-return- Indicates rotate logs at bootup (default: true )
} values
De ne whether more than one constraint on a return value may file.async
be marked for cascading validation are allowed. (default: false ). Log asynchronously (default: false )
And use it normally:
Logging file async queue-length
The queue length to use before ushing writing (default: 512 ) You can con gure the output to be in GELF format instead of plain JSON output is "pretty-printed" (default: false)
text.
file.async.overflow json.date-format
Action when queue is full (default: BLOCK ) ./mvnw quarkus:add-extension Specify the date format to use (default: the default format)
-Dextensions="quarkus-logging-gelf"
syslog.enable json.record-delimiter
syslog logging is enabled (default: false ) Record delimiter to add (default: no delimiter)
handler.gelf.enabled
syslog.format Enable GELF logging handler (default: false ) json.zone-id
The format pattern to use for logging to syslog. Default value: The time zone ID
%d{yyyy-MM-dd HH:mm:ss,SSS} %h %N[%i] %-5p [%c{3.}] (%t) %s%e%n handler.gelf.host
Hostname/IP of Logstash/Graylof. Prepend tcp: for using TCP json.exception-output-type
syslog.level protocol. (default: udp:localhost ) The exception output type: detailed , formatted , detailed-and-
The minimum log level to write to syslog (default: ALL ) formatted (default: detailed )
handler.gelf.port
syslog.endpoint The port. (default: 12201 ) json.print-details
The IP address and port of the syslog server (default: Detailed caller information should be logged (default: false)
localhost:514 ) handler.gelf.version
GELF version. (default: 1.1 ) Rest Client
syslog.app-name
The app name used when formatting the message in RFC5424 handler.gelf.extract-stack-trace Quarkus implements MicroPro le Rest Client spec:
format (default: current process name) Post Stack-Trace to StackTrace eld. (default: true )
./mvnw quarkus:add-extension
syslog.hostname handler.gelf.stack-trace-throwable-reference -Dextensions="quarkus-rest-client"
The name of the host the messages are being sent from (default: Gets the cause level to stack trace. 0 is fulls tack trace. (default:
current hostname) 0)
To get content from http://worldclockapi.com/api/json/cet/now
syslog.facility handler.gelf.filter-stack-trace you need to create a service interface:
Priority of the message as de ned by RFC-5424 and RFC-3164 Stack-Trace ltering. (default: false )
(default: USER_LEVEL ) @Path("/api")
handler.gelf.timestamp-pattern @RegisterRestClient
syslog.syslog-type public interface WorldClockService {
Java Date pattern. (default: yyyy-MM-dd HH:mm:ss,SSS )
The syslog type of format message (default: RFC5424 )
handler.gelf.level
@GET @Path("/json/cet/now")
syslog.protocol @Produces(MediaType.APPLICATION_JSON)
Log level java.util.logging.Level . (default: ALL ) WorldClock getNow();
Protocol used (default: TCP )

handler.gelf.facility
@GET
syslog.use-counting-framing
Name of the facility. (default: jboss-logmanage ) @Path("/json/{where}/now")
Message pre xed with the size of the message (default false ) @Produces(MediaType.APPLICATION_JSON)
handler.gelf.additional-field.<field>.<subfield> WorldClock getSauce(@BeanParam
syslog.truncate WorldClockOptions worldClockOptions);
Post additional elds. quarkus.log.handler.gelf.additional-
Message should be truncated (default: true ) field.field1.type=String
}
syslog.block-on-reconnect JSON output
Block when attempting to reconnect (default: true )
You can con gure the output to be in JSON format instead of plain
text. public class WorldClockOptions {
syslog.async
@HeaderParam("Authorization")
Log asynchronously (default: false ) String auth;
./mvnw quarkus:add-extension

syslog.async.queue-length -Dextensions="quarkus-logging-json"
@PathParam("where")
The queue length to use before ushing writing (default: 512 ) String where;
}
syslog.async.overflow And the con guration values are pre x with quarkus.log :
Action when queue is full (default: BLOCK )
json
And con gure the hostname at application.properties :
Gelf ouput JSON logging is enabled (default: true).

json.pretty-print
org.acme.quickstart.WorldClockService/mp-rest/url=
Reactive import
http://worldclockapi.com org.jboss.resteasy.annotations.providers.multipart.Mult
Rest Client also integrates with reactive library named Mutiny. To
ipartForm;
start using it you need to add the quarkus-rest-client-mutiny .

After that, a methodon a client interface can return a @Path("/echo")
Injecting the client:
io.smallrye.mutiny.Uni instance. @RegisterRestClient
public interface MultipartService {
@RestClient
WorldClockService worldClockService; @GET @Path("/json/cet/now")
@POST
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.MULTIPART_FORM_DATA)
Uni<WorldClock> getNow();
@Produces(MediaType.TEXT_PLAIN)
If invokation happens within JAX-RS, you can propagate headers String sendMultipartData(@MultipartForm
from incoming to outgoing by using next property. MultipartBody data);
Multipart
}
org.eclipse.microprofile.rest.client.propagateHeaders=
It is really easy to send multipart form-data with Rest Client.
Authorization,MyCustomHeader

<dependency> SSL
<groupId>org.jboss.resteasy</groupId>
You can still use the JAX-RS client without any problem <artifactId>resteasy-multipart-provider</artifactId> You can con gure Rest Client key stores.
ClientBuilder.newClient().target(…
) </dependency>

org.acme.quickstart.WorldClockService/mp-rest/trustStore=
Adding headers
classpath:/store.jks
You can customize the headers passed by implementing The model object: org.acme.quickstart.WorldClockService/mp-rest/trustStorePas
MicroPro le ClientHeadersFactory annotation: sword=
import java.io.InputStream; supersecret

@RegisterForReflection
public class BaggageHeadersFactory import javax.ws.rs.FormParam;
implements ClientHeadersFactory { import javax.ws.rs.core.MediaType; Possible con guration properties:
@Override
public MultivaluedMap<String, String> update( import %s/mp-rest/trustStore
MultivaluedMap<String, String> incomingHeaders, org.jboss.resteasy.annotations.providers.multipart.Part Trust store location de ned with classpath: or file: pre x.
MultivaluedMap<String, String> outgoingHeaders) {} Type;
} %s/mp-rest/trustStorePassword
public class MultipartBody {

Trust store password.
@FormParam("file")
And registering it in the client using RegisterClientHeaders
@PartType(MediaType.APPLICATION_OCTET_STREAM) %s/mp-rest/trustStoreType
annotation. private InputStream file; Trust store type (default: JKS )

@RegisterClientHeaders(BaggageHeadersFactory.class) @FormParam("fileName") %s/mp-rest/hostnameVerifier
@RegisterRestClient @PartType(MediaType.TEXT_PLAIN) Custom hostname veri er class name. To disable SSL veri cation
public interface WorldClockService {} private String name; you can use io.quarkus.restclient.NoopHostnameVerifier .

// getter/setters
%s/mp-rest/keyStore
}
Or statically set: Key store location de ned with classpath: or file: pre x.

@GET %s/mp-rest/keyStorePassword
@ClientHeaderParam(name="X-Log-Level", value="ERROR") And the Rest client interface:
Key store password.
Response getNow();

%s/mp-rest/keyStoreType
Key store type (default: JKS )
Asynchronous
Timeout
A method on client interface can return a CompletionStage class to
be executed asynchronously. You can de ne the timeout of the Rest Client:

@GET @Path("/json/cet/now")
@Produces(MediaType.APPLICATION_JSON)
CompletionStage<WorldClock> getNow();
org.acme.quickstart.WorldClockService/mp-rest/connectTimeou @QuarkusTest
You need to create a class implementing
t= @TestHTTPEndpoint(GreetingResource.class)
QuarkusTestResourceLifecycleManager interface and register it in the
1000 public class GreetingResourceTest {
test via @QuarkusTestResource annotation.
org.acme.quickstart.WorldClockService/mp-rest/readTimeout= @Test
2000 public void testHelloEndpoint() {
given() public class MyCustomTestResource
.when().get() implements QuarkusTestResourceLifecycleManager {
.then()
Instantiate client programmatically @Override
.statusCode(200)
.body(is("hello")); public Map<String, String> start() {
MovieReviewService reviewSvc = RestClientBuilder.newBuilder } // return system properties that
() } // should be set for the running test
.baseUri(apiUri) return Collections.emptyMap();
.build(WorldClockService.class); }

Root path is calculated automatically, not necessary to explicitly @Override
set. public void stop() {
Testing }
If you want any changes made to be rolled back at the end ofthe
Quarkus archetype adds test dependencies with JUnit 5 and Rest- test you can use the io.quarkus.test.TestTransaction annotation.
// optional
Assured library to test REST endpoints. @Override
QuarkusTestPro le
public void inject(Object testInstance) {
@QuarkusTest You can de ne for each Test class a different con guration options. }
public class GreetingResourceTest {
// optional
@Test This implies that the Quarkus service is restarted. @Override
public void testHelloEndpoint() { public int order() {
given() return 0;
.when().get("/hello") public class MyProfile implements io.quarkus.test.junit.Qua }
.then() rkusTestProfile { }
.statusCode(200)
.body(is("hello")); @Override
} public Map<String, String> getConfigOverrides() {
} return Map.of("greetings.message", "This is a Test" Returning new system properties implies running parallel
); tests in different JVMs.
}
And the usage:
Test port can be set in quarkus.http.test-port property. Timeout @Override
can be set in quarkus.http.test-timeout property. public String getConfigProfile() { @QuarkusTestResource(MyCustomTestResource.class)
return "my-test-profile"; public class MyTest {
You can also inject the URL where Quarkus is started: } }
}
@TestHTTPResource("index.html")
URL url; @QuarkusTest
@TestProfile(MyProfile.class) Testing Callbacks
public class MyTestClass {
You can enrich all your @QuarkusTest classes by implementing the
}
@TestHTTPEndpoint(GreetingResource.class) following callback interfaces:
@TestHTTPResource
URL url; io.quarkus.test.junit.callback.QuarkusTestBeforeClassCallback
Quarkus Test Resource
io.quarkus.test.junit.callback.QuarkusTestAfterConstructCall
You can execute some logic before the rst test run ( start ) and back
execute some logic at the end of the test suite ( stop ).
io.quarkus.test.junit.callback.QuarkusTestBeforeEachCallback

io.quarkus.test.junit.callback.QuarkusTestAfterEachCallback

public class SimpleAnnotationCheckerBeforeClassCallback imp


lements QuarkusTestBeforeClassCallback {
@Override
public void beforeClass(Class<?> testClass) {
}
}
And needs to be registered as Java SPI: To Mock REST Client, you need to de ne the interface with Persistence
@ApplicationScope :
META-
INF/services/io.quarkus.test.junit.callback.QuarkusTestBeforeClassCallback Quarkus works with JPA(Hibernate) as persistence solution. But
@ApplicationScoped also provides an Active Record pattern implementation under
io.quarkus.it.main.SimpleAnnotationCheckerBeforeClassCallba @RegisterRestClient Panache project.
ck public interface GreetingService {
} To use database access you need to add Quarkus JDBC drivers
instead of the original ones. At this time Apache Derby , H2 , MariaDB ,
Mocking @InjectMock MySQL , MSSQL and PostgreSQL drivers are supported.
@RestClient
If you need to provide an alternative implementation of a service GreetingService greetingService; ./mvnw quarkus:add-extension
(for testing purposes) you can do it by using CDI @Alternative -Dextensions="io.quarkus:quarkus-hibernate-orm-panache,
annotation using it in the test service placed at src/test/java : Mockito.when(greetingService.hello()).thenReturn("hello fro io.quarkus:quarkus-jdbc-mariadb"
m mockito");
@Alternative
@Priority(1)
@Entity
@ApplicationScoped Interceptors
public class MockExternalService extends ExternalService {} public class Developer extends PanacheEntity {
Tests are actually full CDI beans, so you can apply CDI interceptors:
// id field is implicit

@QuarkusTest
public String name;
This does not work when using native image testing. @Stereotype
}
@Transactional
@Retention(RetentionPolicy.RUNTIME)
A stereotype annotation io.quarkus.test.Mock is provided declaring
@Target(ElementType.TYPE)
@Alternative , @Priority(1) and @Dependent .
public @interface TransactionalQuarkusTest { And con guration in src/main/resources/application.properties :
}
Mockito
quarkus.datasource.jdbc.url=jdbc:mariadb://localhost:3306/m
Instead of creating stubs, you can also create mocks of your @TransactionalQuarkusTest ydb
services with mockito. Add the following dependency public class TestStereotypeTestCase {} quarkus.datasource.db-kind=mariadb
io.quarkus:quarkus-junit5-mockito : quarkus.datasource.username=developer
quarkus.datasource.password=developer
@InjectMock Test Coverage Due the nature of Quarkus to calculate correctly the quarkus.hibernate-orm.database.generation=update
GreetingService greetingService; coverage information with JaCoCo, you might need o ine
instrumentation. I recommend reading this document to
@BeforeEach understand how JaCoCo and Quarkus works and how you can List of datasource parameters.
public void setup() { con gure JaCoCo to get correct data.
Mockito.when(greetingService.greet()).thenReturn("Hi"); quarkus.datasource as pre x is skipped in the next table.
} Native Testing
db-kind
To test native executables annotate the test with @NativeImageTest .
@Path("/hello") Built-in datasource kinds so the JDBC driver is resolved
public class ExampleResource { automatically. Possible values: derby , h2 , mariadb , mssql , mysql ,
postgresql , db2 .
@Inject
GreetingService greetingService; username
}
Username to access.

password
Mock is automatically injected and only valid for the de ned test Password to access.
class.
driver
Also spy is supported:
JDBC Driver class. It is not necessary to set if db-kind used.
@InjectSpy
credentials-provider
GreetingService greetingService;
Sets a custom credential provider name.
Mockito.verify(greetingService, Mockito.times(1)).greet();
credentials-provider-name
It is the @Named value of the credentials provider bean. Not
REST Client necessary if only one implementation.
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
Database schema is generation. Possible values: none , create ,

Warn when a connection is returned to the pool without the // Hibernate Filters
drop-and-create , drop , update . (default: none )
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
delete : String , [ Object… , Map<String, Object> , Parameters ] <execution>
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
try/catch block: try (Stream<Person> persons = Person.streamAll()) . </dependency>
by Sort attribute/s. Returning a PanacheQuery .
</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 {
To mock using active record pattern:
Returning a List .
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 DAO pattern
streamAll
java.util.stream.Stream of all entities. Also supports DAO pattern with PanacheRepository<TYPE> .
PanacheQuery<Person> livingPersons = Person
.find("status", Status.Alive);
streamAll : Sort List<Person> secondRange = livingPersons.range(25, 49).list
java.util.stream.Stream of all entities sorted by Sort attribute/s. ();

count
Number of entities You cannot mix pagination and range
You can implement your custom credentials provider (ie Azure
@ApplicationScoped @QuarkusTestResource(H2DatabaseTestResource.class)
public class DeveloperRepository public class FlywayTestResources {
KeyVault) to provide a username/password for the database
connection. Name information is not necessary if there is only one
implements PanacheRepository<Person> { }
custom credential provider.
public Person findByName(String name){
return find("name", name).firstResult();
} @ApplicationScoped
Transactions
} @Unremovable
@Named("my-credentials-provider")
The easiest way to de ne your transaction boundaries is to use the
public class CustomCredentialsProvider implements Credentia
@Transactional annotation.
lsProvider {
EntityManager You can inject EntityManager in your classes: @Inject
Transactions are mandatory in case of none idempotent
operations. Config config;
@Inject
EntityManager em; @Override
@Transactional
public Properties getCredentials(String credentials
em.persist(car); public void createDeveloper() {}
ProviderName) {

properties.put(CredentialsProvider.USER_PROPERTY_NA
Multiple datasources You can control the transaction scope: ME, "hibernate_orm_test");
properties.put(CredentialsProvider.PASSWORD
You can register more than one datasource. @Transactional(REQUIRED) (default): starts a transaction if none _PROPERTY_NAME, "hibernate_orm_test");
was started, stays with the existing one otherwise.
}
# default @Transactional(REQUIRES_NEW) : starts a transaction if none was
}
quarkus.datasource.db-kind=h2 started; if an existing one was started, suspends it and starts a
quarkus.datasource.jdbc.url=jdbc:h2:tcp://localhost/mem:def new one for the boundary of that method.
ault
.... @Transactional(MANDATORY) : fails if no transaction was started ; quarkus.datasource.credentials-provider=
# users datasource works within the existing transaction otherwise. custom
quarkus.datasource.users.db-kind=h2
quarkus.datasource.credentials-provider-name=
quarkus.datasource.users..jdbc.url=jdbc:h2:tcp://localhost/ @Transactional(SUPPORTS) : if a transaction was started, joins it ;
my-credentials-provider
mem:users otherwise works with no transaction.

@Transactional(NOT_SUPPORTED) :
if a transaction was started,
suspends it and works with no transaction for the boundary of Hibernate Multitenancy
Notice that after datasource you set the datasource name, in
the method; otherwise works with no transaction.
previous case users . Multitenancy is supported using Schema or Database approach.
@Transactional(NEVER) : if a transaction was started, raises an First you need to de ne how tenant is identi ed:
You can inject then AgroalDataSource with
exception; otherwise works with no transaction.
io.quarkus.agroal.DataSource .
@RequestScoped
You can con gure the default transaction timeout using
@Unremovable
@DataSource("users") quarkus.transaction-manager.default-transaction-timeout
public class CustomTenantResolver implements TenantResolver
AgroalDataSource dataSource1; con guration property. By default it is set to 60 seconds.
{

You can set a timeout property, in seconds, that applies to
@Inject
transactions created within the annotated method by using
Flushing RoutingContext context;
@TransactionConfiguration annotation.

You can force ush operation by calling .flush() or @Override
.persistAndFlush() to make it in a single call. @Transactional public String getDefaultTenantId() {
@TransactionConfiguration(timeout=40) return "base";
This ush is less e cient and you still need to commit public void createDeveloper() {} }
transaction.
@Override
Testing If you want more control over transactions you can inject public String resolveTenantId() {
UserTransaction and use a programmatic way. }
There is a Quarkus Test Resource that starts and stops H2 server
before and after test suite. }
@Inject UserTransaction transaction

Register dependency io.quarkus:quarkus-test-h2:test .
transaction.begin();
And annotate the test: transaction.commit(); Schema approach
transaction.rollback();
quarkus.hibernate-orm.database.generation=none public interface DeveloperResource extends PanacheRepositor @Entity
yResource<DeveloperRepository, Developer, Long> { @Table(name = "dev")
quarkus.hibernate-orm.multitenant=SCHEMA } public class Developer {
}

@Inject
Database approach Quarkus will generate automatically the implementation for you
CompletionStage<Stage.Session> stageSession;
following the next rules:

quarkus.hibernate-orm.database.generation=none @Inject

Default path is a hyphenated lowercase resource name
without a su x of resource or controller . Uni<Mutiny.Session> mutinySession;
quarkus.hibernate-orm.multitenant=DATABASE

get(@PathParam("id")) , list , add(Developer) , public Uni<Long> reactivePersist() {
# default tenant
update(@PathParam("id"), Developer) , delete(@PathParam("id")) return mutinySession
quarkus.datasource.base.db-kind=postgresql .flatMap(s -> s.persist(new Developer(1, "Alex"))
quarkus.datasource.base.username=quarkus_test You can customize these defaults by using @ResourceProperties and .flatMap(v -> session.flush())
... @MethodProperties annotations. ....
# Tenant 'mycompany'
quarkus.datasource.mycompany.db-kind=postgresql }
@ResourceProperties(hal = true, path = "my-developer")
quarkus.datasource.mycompany.username=mycompany
public interface DeveloperResource extends PanacheEntityRes
quarkus.flyway.mycompany.locations=classpath:database/mycom public CompletionStage<Developer> reactiveFind() {
ource<Developer, Long> {
pany return stageSession
@MethodProperties(path = "all")
... .thenCompose(session -> {
List<Developer> list();
@MethodProperties(exposed = false) session.find(Developer.class, 1);
void delete(Long id); });
If you need more dynamic approach implement: @ApplicationScoped } }
io.quarkus.hibernate.orm.runtime.tenant.TenantConnectionResolver

Hibernate Envers If hal is true , you need to send the Accept: application/hal+json In nispan
HTTP header to get the response.
Quarkus supports Hibernate Envers. Quarkus integrates with In nispan:
Hibernate Reactive
./mvnw quarkus:add-extension
./mvnw quarkus:add-extension
-Dextensions="hibernate-envers"
./mvnw quarkus:add-extension -Dextensions="infinispan-client"
-Dextensions="quarkus-hibernate-reactive, quarkus-resteas
y-mutiny, "
REST Data Panache Serialization uses a library called Protostream.

REST Data with Panache extension can generate the basic CRUD Annotation based
Also you need to add the reactive driver (ie quarkus-reactive-pg-
endpoints for your entities and repositories. client ).
@ProtoFactory
./mvnw quarkus:add-extension You can use: org.hibernate.reactive.mutiny.Mutiny or public Author(String name, String surname) {
-Dextensions="hibernate-orm-rest-data-panache" org.hibernate.reactive.stage.Stage . this.name = name;
this.surname = surname;
}

You also need to add the JDBC driver extension and a JSON
@ProtoField(number = 1)
Marshaller (ie resteasy-jackson ).
public String getName() {
return name;
Then you can de ne interfaces for de ning endpoints:
}
In case of Active Record pattern:
@ProtoField(number = 2)
public String getSurname() {
public interface DeveloperResource extends PanacheEntityRes
return surname;
ource<Developer, Long> {
}
}

Initializer to set con guration settings.


In case of Repository:
@AutoProtoSchemaBuilder(includeClasses = public class AuthorMarshaller
Con guration in infinispan.xml :
{ Book.class, Author.class }, implements MessageMarshaller<Author> {
schemaPackageName = "book_sample")
interface BookContextInitializer @Override <local-cache name="quarkus-transaction">
extends SerializationContextInitializer { public String getTypeName() { <transaction
} return "book_sample.Author"; transaction-manager-lookup=
} "org.infinispan.transaction.lookup.JBossStandaloneJ
TAManagerLookup"/>
@Override </local-cache>
User written based
public Class<? extends Author> getJavaClass() {
There are three ways to create your schema: return Author.class;
} Set con guration le location in application.properties :
Proto le
@Override
quarkus.infinispan-embedded.xml-config=infinispan.xml
Creates a .proto le in the META-INF directory. public void writeTo(ProtoStreamWriter writer,
Author author) throws IOException {
package book_sample; writer.writeString("name", author.getName());
writer.writeString("surname", author.getSurname()); And you can inject the main entry point for the cache:
message Author { }
required string name = 1; @Inject
required string surname = 2; @Override org.infinispan.manager.EmbeddedCacheManager cacheManager;
} public Author readFrom(ProtoStreamReader reader)
throws IOException {
String name = reader.readString("name");
String surname = reader.readString("surname"); Redis
In case of having a Collection eld you need to use the repeated key return new Author(name, surname);
(ie repeated Author authors = 4 ). } Quarkus integrates with Redis.
}
In code
./mvnw quarkus:add-extension
Setting proto schema directly in a produced bean. -Dextensions="redis-client"
And producing the marshaller:
@Produces
FileDescriptorSource bookProtoDefinition() { @Produces Con gure Redis location:
return FileDescriptorSource MessageMarshaller authorMarshaller() {
.fromString("library.proto", return new AuthorMarshaller(); quarkus.redis.hosts=localhost:6379
"package book_sample;\n" + }
"message Author {\n" +
" required string name = 1;\n" +
" required string surname = 2;\n" +
You can use synchronous or reactive clients:
In nispan Embedded
"}");
} @Inject
./mvnw quarkus:add-extension RedisClient redisClient;
-Dextensions="infinispan-embeddedy"
@Inject
Marshaller
ReactiveRedisClient reactiveRedisClient;

Using org.infinispan.protostream.MessageMarshaller interface.


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") Multiple Datasources
List of Flyway parameters.
RedisClient redisClient2;
quarkus.flyway as pre x is skipped in the next table. To use multiple datasource in Flyway you just need to add the
datasource name just after the flyway property:
clean-at-start
List of Redis parameters.
Execute Flyway clean command (default: false ) quarkus.datasource.users.jdbc.url=jdbc:h2:tcp://localhost/m
quarkus.redis as pre x is skipped in the next table. em:users
migrate-at-start quarkus.datasource.inventory.jdbc.url=jdbc:h2:tcp://localho
health.enabled st/mem:inventory
Flyway migration automatically (default: false )
Health check is published in case the smallrye-health extension # ...
is present. (default: true ) locations

quarkus.flyway.users.schemas=USERS_TEST_SCHEMA
CSV locations to scan recursively for migrations. Supported quarkus.flyway.inventory.schemas=INVENTORY_TEST_SCHEMA
password
pre xes classpath and filesystem (default:
The Redis password. # ...
classpath:db/migration ).

hosts connect-retries
The Redis hosts. (default: localhost:6379 ) The maximum number of retries when attempting to connect Liquibase
(default: 0)
database Quarkus integrates with Liquibase to help you on database schema
The Redis database. schemas migrations.
CSV case-sensitive list of schemas managed (default: none)
timeout ./mvnw quarkus:add-extension
The maximum delay to wait before a blocking command to redis table -Dextensions="quarkus-liquibase"
server times out. (default: 10s ) The name of Flyway’s schema history table (default:
flyway_schema_history )
ssl Then place changelog les to the ( src/main/resources/db ) folder.
Enables or disables the SSL on connect. out-of-order
You can inject org.quarkus.liquibase.LiquibaseFactory to
Allows migrations to be run "out of order". programmatically execute the migration.
clinet-type
The Redis client type. Possible values: standalone , cluster , ignore-missing-migrations
sentinel (default: standalone ) Ignore missing migrations when reading the history table.
liquibase-schema-name
@Inject public class MyQuarkusAnalysisConfigurer
LiquibaseFactory liquibaseFactory; The liquibase tables schema name. implements ElasticsearchAnalysisConfigurer {

try (Liquibase liquibase = liquibaseFactory.createLiquibase liquibase-tablespace-name @Override
()) { 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()

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


datasource name just after the liquibase property: .withTokenizer("standard")
.withTokenFilters("asciifolding",
property to true .
"lowercase", "porter_stem");
quarkus.datasource.users.jdbc.url=jdbc:h2:tcp://localhost/m

quarkus.liquibase.migrate-at-start=true em:users
ctx.normalizer("sort").custom()
quarkus.datasource.inventory.jdbc.url=jdbc:h2:tcp://localho
.withTokenFilters("asciifolding", "lowercase");
st/mem:inventory
}
# ...
List of Liquibase parameters.
}

quarkus.liquibase.users.schemas=USERS_TEST_SCHEMA
quarkus.liquibase as pre x is skipped in the next table.
quarkus.liquibase.inventory.schemas=INVENTORY_TEST_SCHEMA

change-log
# ... Use Hibernate Search in REST service:
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>"
EntityManager em;
Liquibase changelog parameters. Quarkus integrates with Elasticsearch to provide a full-featured full-

text search using Hibernate Search API.
@Transactional
migrate-at-start public List<Author> searchAuthors(
The migrate at start ag. (default: false ) ./mvnw quarkus:add-extension @QueryParam("pattern") String pattern) {
-Dextensions="quarkus-hibernate-search-elasticsearch" return Search.getSearchSession(em)
validate-on-migrate .search(Author.class)
.predicate(f ->
The validate on update ag. (default: false )
You need to annotate your model with Hibernate Search API to pattern == null || pattern.isEmpty() ?

clean-at-start index it: f.matchAll() :


f.simpleQueryString()
The clean at start ag. (default: false ) .onFields("firstName",
@Entity
"lastName", "books.title")
@Indexed
contexts .matching(pattern)
public class Author extends PanacheEntity {
The list of contexts.
)
.sort(f -> f.byField("lastName_sort")
@FullTextField(analyzer = "english")
labels public String bio;
.then().byField("firstName_sort"))
.fetchHits();
The list of labels.
}
@FullTextField(analyzer = "name")
database-change-log-table-name @KeywordField(name = "firstName_sort",
The database change log lock table name. (default: sortable = Sortable.YES,
DATABASECHANGELOG )
normalizer = "sort") When not using Hibernate ORM, index data using
public String firstName; Search.getSearchSession(em).createIndexer()
database-change-log-lock-table-name .startAndWait() at startup time.
@OneToMany
The database change log lock table name. (default: @IndexedEmbedded Con gure the extension in application.properties :
DATABASECHANGELOGLOCK )
public List<Book> books;

default-catalog-name quarkus.hibernate-search.elasticsearch.version=7
}
quarkus.hibernate-search.elasticsearch.
The default catalog name. analysis-configurer=MyQuarkusAnalysisConfigurer
quarkus.hibernate-search.elasticsearch.
default-schema-name automatic-indexing.synchronization-strategy=searchable
The default schema name. It is not mandatory to use Panache. quarkus.hibernate-search.elasticsearch.
index-defaults.lifecycle.strategy=drop-and-create
liquibase-catalog-name You need to de ne the analyzers and normalizers de ned in quarkus.hibernate-search.elasticsearch.
The liquibase tables catalog name. index-defaults.lifecycle.required-status=yellow
annotations. You only need to implement
ElasticsearchAnalysisConfigurer interface and con gure it.
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
Set if index should be refreshed after writes. Uni.createFrom().completionStage(() -> dynamoDB.scan(scanRe
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
List of Elasticsearch servers hosts. @KeywordField quarkus.dynamodb.credentials.type=STATIC
The string is kept as one single token but can be normalized. quarkus.dynamodb.credentials.static-provider
username .access-key-id=test-key
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
Sets how to extract a value from container, e.g from a Map . If you want to work with an AWS account, you’d need to set it with:
connection-timeout
Duration of connection timeout. @DocumentId quarkus.dynamodb.region=<YOUR_REGION>
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
Reference to the identi er bridge to use for a @DocumentId . Env. Varables AWS_ACCESS_KEY_ID , AWS_SECRET_ACCESS_KEY
indexes
Per-index speci c con guration. @IndexingDependency Credentials pro le ~/.aws/credentials
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
automatic-indexing.synchronization-strategy Quarkus integrates with https://aws.amazon.com/dynamodb/: Endpoint discovery
Status for which you wait before considering the operation enable-endpoint- for a service API that
false
completed ( queued , committed or searchable ). discovery supports endpoint
./mvnw quarkus:add-extension
discovery.
-Dextensions="quarkus-amazon-dynamodb"
automatic-indexing.enable-dirty-check
When enabled, re-indexing of is skipped if the changes are on Con gure the
properties that are not used when indexing. endpoint with which
@Inject endpoint-override
DynamoDbClient dynamoDB;
the SDK should
index-defaults.lifecycle.strategy communicate.
Index lifecycle ( none , validate , update , create , drop-and-create ,
drop-abd-create-drop )
To use asycnhronous client with Mutiny: Time to complete an
api-call-timeout
index-defaults.lifecycle.required-status
execution.
./mvnw quarkus:add-extension
Minimal cluster status ( green , yellow , red )
-Dextensions="quarkus-amazon-dynamodb, resteasy-mutiny"
interceptors List of class
index-defaults lifecycle required-status-wait-timeout interceptors
Parameter Default Description Parameter Default Description
Con guration parameters pre xed with quarkus.dynamodb.aws :
Command to execute proxy.enabled false Enables HTTP proxy.
process-
Parameter Default Description to retrieve
provider.command
credentials.
proxy.username Proxy username.
Region that hosts
region
DynamoDB.
process-
Max bytes to retrieve
provider.process- 1024 proxy.password Proxy password.
from process.
output-limit
Credentials that
should be used For NTLM, domain
DEFAULT , STATIC , proxy.ntlm-domain
The amount of time name.
SYSTEM_PROPERTY , process-
credentials.type DEFAULT between credentials
ENV_VARIABLE , provider.credential- PT15S
expire and
PROFILE , CONTAINER , refresh-threshold
For NTLM,
credentials refreshed. proxy.ntlm-
INSTANCE_PROFILE , workstation workstation name.
PROCESS , ANONYMOUS

process-
provider.async- Should fetch proxy.preemptive-
Authenticate pre-
Credentials speci c parameters pre xed with false
credential-update- credentials async. basic-authentication-
emptively.
quarkus.dynamodb.aws.credentials :
enabled enabled

Parameter Default Description


In case of synchronous client, the next parameters can be proxy.non-proxy- List of non proxy
DEFAULT con gured pre xed by quarkus.dynamodb.sync-client : hosts hosts.

Parameter Default Description


default- TLS manager: none ,
tls-managers-
provider.async- Should fetch system-property system-property ,
false connection- Connection provider.type
credential-update- credentials async. 10S file-store
acquisition-timeout acquisation timeout.
enabled

Max time to tls-managers-


default- Should reuse the last connection-max-idle- provider.file- Path to key store.
60S connection to be
provider.reuse-last- true successful time store.path
opened.
provider-enabled credentials.

connection-timeout Connection timeout. tls-managers-


STATIC provider.file- Key store type.
store.type
connection-time-to- Max time connection
static- 0
live to be open.
provider.access-key- AWS access key id. tls-managers-
id provider.file- Key store password.
socket-timeout 30S Time to wait for data. store.password

static-
AWS secret access
provider.secret-
key. max-connections 50 Max connections. In case of asynchronous client, the next parameters can be
access-key con gured pre xed by quarkus.dynamodb.async-client :

Client send an HTTP Parameter Default Description


PROFILE expect-continue-
true expect-continue
enabled
handsake. connection- Connection
10S
acquisition-timeout acquisation timeout.
profile- The name of the
default
provider.profile-name pro le to use. Connections in pool
use-idle-connection-
true should be closed Max time to
reaper connection-max-idle-
asynchronously. 60S connection to be
PROCESS time
opened.

Endpoint of the proxy


proxy.endpoint
server. connection-timeout Connection timeout.
Parameter Default Description Parameter Default Description @Inject
S3AsyncClient s3AsyncClient;
connection-time-to- Max time connection Enable custom event
0 event-loop.override false
live to be open. loop conf.
And you need to add the asynchronous Netty client:
Max number of event-loop.number-of- Number of threads to
max-concurrency 50 concurrent threads use in event loop. <dependency>
connections. <groupId>software.amazon.awssdk</groupId>
<artifactId>netty-nio-client</artifactId>
event-loop.thread- aws-java-sdk- Pre x of thread </dependency>
Connections in pool name-prefix NettyEventLoop names.
use-idle-connection-
true should be closed
reaper
asynchronously.
Con guration properties are the same as Amazon DynamoDB but
Amazon S3 changing the pre x from dynamodb to s3 .
read-timeout 30S Read timeout.
./mvnw quarkus:add-extension Neo4j
-Dextensions="quarkus-amazon-s3"
write-timeout 30S Write timeout. Quarkus integrates with Neo4j:

./mvnw quarkus:add-extension
Endpoint of the proxy @Inject
-Dextensions="quarkus-neo4j"
proxy.endpoint
server. S3Client s3Client;

proxy.enabled false Enables HTTP proxy. You need to set a HTTP client either URL Connection : @Inject
org.neo4j.driver.Driver driver;

proxy.non-proxy- List of non proxy <dependency>


hosts hosts. <groupId>software.amazon.awssdk</groupId>
<artifactId>url-connection-client</artifactId> Con guration properties:
</dependency>
TLS manager: none , quarkus.neo4j as pre x is skipped in the next table.
tls-managers-
system-property system-property ,
provider.type Pre x is quarkus.neo4j .
file-store or Apache HTTP:
uri
<dependency> URI of Neo4j. (default: localhost:7687 )
tls-managers-
<groupId>software.amazon.awssdk</groupId>
provider.file- Path to key store.
<artifactId>apache-client</artifactId> authentication.username
store.path
</dependency>
Username. (default: neo4j )

tls-managers- authentication.password
provider.file- Key store type.
quarkus.s3.sync-client.type=apache Password. (default: neo4j )
store.type

authentication.disabled
tls-managers- And con gure it: Disable authentication. (default: false )
provider.file- Key store password.
store.password quarkus.s3.endpoint-override=http://localhost:8008 pool.metrics-enabled
quarkus.s3.interceptors=io.quarkus.it.amazon.s3.S3ModifyRes Enable metrics. (default: false )
ponse
SSL Provider ( jdk , quarkus.s3.aws.region=us-east-1 pool.log-leaked-sessions
ssl-provider openssl , openssl-
quarkus.s3.aws.credentials.type=static
refcnt ). Enable leaked sessions logging. (default:`false`)
quarkus.s3.aws.credentials.static-provider.access-key-id=te
st-key
pool.max-connection-pool-size
quarkus.s3.aws.credentials.static-provider.secret-access-ke
Sets the HTTP Max amount of connections. (default: 100 )
protocol HTTP_1_1 y=test-secret
protocol.
pool.max-connection-lifetime

Max number of You can inject asynchronous client too: Pooled connections older will be closed and removed from the
max-http2-streams
concurrent streams. pool. (default: 1H )
pool.connection-acquisition-timeout
./mvnw quarkus:add-extension Parameter Type Description
Timout for connection adquisation. (default: 1M) -Dextensions="quarkus-mongodb-client"
max-connection-idle- Idle time of a pooled
Duration
pool.idle-time-before-connection-test time connection.
Pooled connections idled in the pool for longer than this timeout
@Inject
will be tested before they are used. (default: -1 )
com.mongodb.client.MongoClient client; max-connection-life- Life time of pooled
Duration
time connection.
As Neo4j uses SSL communication by default, to create a native
@Inject
executable you need to compile with next options GraalVM options:
io.quarkus.mongodb.reactive.ReactiveMongoClient client;
Maximum wait time
-H:EnableURLProtocols=http,https --enable-all-security-services - wait-queue-timeout Duration
for new connection.
H:+JNI
INFO: Reactive client uses exposes Mutiny API.
And Quarkus Maven Plugin with next con guration:
Time period between
maintenance-
quarkus.mongodb.connection-string=mongodb://localhost:27018 Duration runs of maintenance
<artifactId>quarkus-maven-plugin</artifactId> frequency
quarkus.mongodb.write-concern.journal=false job.
<executions>
<execution>
<id>native-image</id> Time to wait before
Multi MongoDB support maintenance-initial-
<goals> Duration running the rst
delay
<goal>native-image</goal>
You can con gure multiple MongoDB clients using same approach maintenance job.
</goals>
as with DataSource . The syntax is quarkus.mongodb.<optional name>.
<configuration>
<property> :
<enableHttpUrlHandler>true Multiplied with max-
</enableHttpUrlHandler> pool-size gives max
quarkus.mongodb.users.connection-string = mongodb://mongo2: wait-queue-multiple Int
<enableHttpsUrlHandler>true numer of threads
</enableHttpsUrlHandler> 27017/userdb waiting.
<enableAllSecurityServices>true quarkus.mongodb.inventory.connection-string = mongodb://mon
</enableAllSecurityServices> go3:27017/invdb
<enableJni>true</enableJni> connection-timeout Duration
</configuration>
</execution> Inject the instance using
</executions> socket-timeout Duration
@io.quarkus.mongodb.runtime.MongoClientName annotation:

@Inject tls-insecure boolean [false] Insecure TLS.


Alternatively, and as a not recommended way in production, you @MongoClientName("users")
can disable SSL and Quarkus will disable Bolt SSL as well. MongoClient mongoClient1;
quarkus.ssl.native=false . tls boolean [false] Enable TLS
If you are using Neo4j 4.0, you can use fully reactive. Add the next
quarkus.mongodb as pre x is skipped in the next table.
extension: quarkus-resteasy-mutiny . Implies hosts given
replica-set-name String
Parameter Type Description are a seed list.
@GET
public Publisher<String> get() {
MongoDB connection
return Multi.createFrom().resource(driver::rxSession, connection-string String server-selection- Time to wait for
URI. Duration
session -> session.readTransaction(tx -> { timeout server selection.
RxResult result = tx.run("MATCH (f:Fruit) RETUR
N f.name as name"); Addresses passed as
return Multi.createFrom().publisher(result.reco hosts List<String> Minimum ping time
host:port .
rds()) local-threshold Duration to make a server
.map(record -> record.get("name").asStr eligible.
ing()); application-name String Application name.
})
).withFinalizer(session -> { Frequency to
return Uni.createFrom().publisher(session.close()); Maximum number of heartbeat-frequency Duration determine the state
});
max-pool-size Int
connections. of servers.
}

Minimum number of
min-pool-size Int
connections.
MongoDB Client
Q k i i hM DB
Parameter Type Description MongoDB con guration comes from MongoDB Client section.
PanacheQuery<Person> livingPersons =
Person.find("status", Status.Alive);
primary , @MongoEntity(collection="ThePerson") livingPersons.page(Page.ofSize(25));
primaryPreferred , public class Person extends PanacheMongoEntity {
read-preference secondary , Read preferences. public String name; // get the first page
secondaryPreferred , List<Person> firstPage = livingPersons.list();
nearest @BsonProperty("birth") // get the second page
public LocalDate birthDate; List<Person> secondPage = livingPersons.nextPage().list();

Max number of public Status status;
concurrent }
max-wait-queue-size Int
operations allowed to Range
wait.
PanacheQuery<Person> livingPersons = Person
Possible annotations in elds: @BsonId (for custom ID), .find("status", Status.Alive);
@BsonProperty and @BsonIgnore .
Ensures are writes List<Person> secondRange = livingPersons.range(25, 49).list
write-concern.safe boolean [true]
are ack. ();
@MongoEntity is optional.

write- Journal writing


boolean [true] You cannot mix pagination and range.
concern.journal aspect. Multi-tenancy with MongoDB Panache
Queries
@MongoEntity(collection = "TheBook", clientName = "client2"
Value to all write , database = "database2") Native MongoDB queries are supported (if they start with { or
write-concern.w String
commands. org.bson.Document instance) as well as Panache Queries. Panache
Queries equivalence in MongoDB:
write-concern.retry- Retry writes if Methods provided are similar of the ones shown in Persistence
boolean [false] firstname = ?1 and status = ?2 → {'firstname': ?1, 'status': ?
writes network fails. section.
2}

person.persist(); amount > ?1 and firstname != ?2 → {'amount': {'$gt': ?1},


write-concern.w- Timeout to all write person.update(); 'firstname': {'$ne': ?2}}
Duration
timeout commands. person.delete();
lastname like ?1 → {'lastname': {'$regex': ?1}}
List<Person> allPersons = Person.listAll();
credentials.username String Username. person = Person.findById(personId); lastname is not null → {'lastname':{'$exists': true}}
List<Person> livingPersons = Person.list("status", Status.A
live); PanacheQL refers to the Object parameter name but native
credentials.password String Password.
List<Person> persons = Person.list(Sort.by("name").and("bir queries refer to MongoDB eld names.
th"));

credentials.auth- MONGO-CR , GSSAPI ,


Projection
long updated = Person.update("name", "Mortal").where("statu
mechanism PLAIN , MONGODB-X509
s", Status.Alive); Projection can be done for both PanacheQL and native queries.

long countAll = Person.count();
Source of the import io.quarkus.mongodb.panache.ProjectionFor;
credentials.auth-
String authentication
source Person.deleteById(id);
credentials. @ProjectionFor(Person.class) (1)
Person.delete("status", Status.Alive); public class PersonName {
public String name;
Authentication }
credentials.auth-
Map<String, String> mechanism All list methods have equivalent stream versions.
mechanism-properties
properties. PanacheQuery<PersonName> shortQuery = Person.find("status "
Pagination , Status.Alive).project(PersonName.class);

MongoDB Panache You can also use pagination:

1 Entity class.
You can also use the Panache framework to write persistence part
when using MongoDB. Testing

./mvnw quarkus:add-extension To mock using active record pattern:


-Dextensions="mongodb-panache"
MongoDB with Panache allows using reactive implementation too You need to create a DaoProducer:
<dependency>
<groupId>io.quarkus</groupId>
by using ReactivePanacheMongoEntity or
ReactivePanacheMongoEntityBase or ReactivePanacheMongoRepository @Inject
<artifactId>quarkus-panache-mock</artifactId>
or ReactivePanacheMongoRepositoryBase depending on your style. public FruitDaoProducer(QuarkusCqlSession session) {
<scope>test</scope>
</dependency> FruitMapper mapper = new FruitMapperBuilder(session).buil
public class ReactivePerson extends ReactivePanacheMongoEnt d();
ity { fruitDao = mapper.fruitDao();
public String name; }
@Test }
public void testPanacheMocking() { @Produces
PanacheMock.mock(Person.class); CompletionStage<Void> cs1 = person.persist(); @ApplicationScoped
CompletionStage<List<ReactivePerson>> allPersons = Reactive FruitDao produceFruitDao() {
Mockito.when(Person.count()).thenReturn(23l); Person.listAll(); return fruitDao;
Assertions.assertEquals(23, Person.count()); Publisher<ReactivePerson> allPersons = ReactivePerson.strea }
PanacheMock.verify(Person.class, Mockito.times(1)).coun mAll();
t();
} Uni<List<PersonName>> persons = ReactivePersonEntity.find(
Cassandra con guration:
"lastname", name).project(PersonName.class).list();

quarkus.cassandra.contact-points=127.0.0.1:9042
DAO pattern quarkus.cassandra.local-datacenter=datacenter1
MongoDB REST Data Panache quarkus.cassandra.keyspace=k1
@ApplicationScoped quarkus.cassandra.auth.username=john
public class PersonRepository MongoDB REST Data with Panache extension can generate the quarkus.cassandra.auth.password=s3cr3t
implements PanacheMongoRepository<Person> { basic CRUD endpoints for your entities and repositories.
}

./mvnw quarkus:add-extension You can con gure other Cassandra Java driver settings using
-Dextensions="mongodb-rest-data-panache" application.conf or application.json les. They need to be located
Jandex in the classpath of your application. Driver settings reference.

If entities are de ned in external JAR, you need to enable in these If MicroPro le Metrics extension is registered, the Cassandra
You also need to add the JDBC driver extension and a JSON
projects the Jandex plugin in project. extension can provide (if enabled) metrics about the session:
Marshaller (ie resteasy-jackson ).
<plugin> Then you can de ne interfaces for de ning endpoints: quarkus.cassandra.metrics.enabled=true
<groupId>org.jboss.jandex</groupId> quarkus.cassandra.metrics.session-enabled=connected-nodes,b
<artifactId>jandex-maven-plugin</artifactId> In case of Active Record pattern: ytes-sent
<version>1.0.3</version> quarkus.cassandra.metrics.node-enabled=pool.open-connection
<executions> public interface DeveloperResource extends PanacheMongoEnti s
<execution> tyResource<Developer, Long> {
<id>make-index</id> }
<goals>
Reactive
<goal>jandex</goal>
</goals> You can also use Mutiny to de ne a reactive DAO:
</execution> In case of Repository:
</executions>
@Dao
<dependencies> public interface DeveloperResource extends PanacheMongoRepo
public interface FruitDaoReactive {
<dependency> sitoryResource<DeveloperRepository, Developer, Long> {

<groupId>org.jboss</groupId> }
@Update
<artifactId>jandex</artifactId>
Uni<Void> update(Fruit fruit);
<version>2.1.1.Final</version>

</dependency>
</dependencies> Cassandra @Select
MutinyMappedReactiveResultSet<Fruit> findById(String stor
</plugin>
Quarkus integrates with Cassandra and DataStax Object Mapper. eId);
}

<dependency>
Panache includes an annotation processor that enhance your @Mapper
<groupId>com.datastax.oss.quarkus</groupId>
entities. If you disable annotation processors you might need to public interface FruitMapper {
<artifactId>cassandra-quarkus-client</artifactId>
create a marker le on Panache archives at META-INF/panache-
</dependency>
archive.marker manually. @DaoFactory
FruitDaoReactive fruitDaoReactive();
Reactive Panache }
Enities and DAOs are generated as you have been doing with
D t St Obj t M
Reactive Programming @GET Uni<Void> uniFromCompletable = Uni.createFrom()
@Produces(MediaType.TEXT_PLAIN) .converter(UniRxConvert
Quarkus implements MicroPro le Reactive spec and uses RXJava2 public Uni<String> hello() { ers.fromCompletable(), completable);
to provide reactive programming model. return Uni.createFrom().item(() -> "hello"); Uni<String> uniFromSingle = Uni.createFrom()
} .converter(UniRxConverters.
./mvnw quarkus:add-extension fromSingle(), single);
-Dextensions="quarkus-smallrye-reactive-streams-operator @GET Uni<String> uniFromObservable = Uni.createFrom()
s" @Produces(MediaType.TEXT_PLAIN) .converter(UniRxConverters.
public Multi<String> multi() { fromObservable(), observable);
return Multi.createFrom().items("hello", "world"); Uni<String> uniFromFlowable = Uni.createFrom()
} .converter(UniRxConverters.
Asynchronous HTTP endpoint is implemented by returning Java fromFlowable(), flowable);
CompletionStage . You can create this class either manually or using
...
MicroPro le Reactive Streams spec:
Mutiny
Multi<Void> multiFromCompletable = Multi.createFrom()
@GET .converter(MultiRxC
Quarkus integrates with Mutiny as reactive programming library:
@Path("/reactive") onverters.fromCompletable(), completable);
@Produces(MediaType.TEXT_PLAIN) Multi<String> multiFromObservable = Multi.createFrom()
./mvnw quarkus:add-extension
public CompletionStage<String> getHello() { .converter(MultiRxC
-Dextensions="mutiny"
return ReactiveStreams.of("h", "e", "l", "l", "o") onverters.fromObservable(), observable);
.map(String::toUpperCase) Multi<String> multiFromFlowable = Multi.createFrom()
.toList() .converter(MultiRxC
.run() onverters.fromFlowable(), flowable);
@ApplicationScoped
.thenApply(list -> list.toString()); ...
public static class ReactiveHello {
}

public Uni<String> greeting() {
return Uni.createFrom().item(() -> "hello") To RxJava2 :
Creating streams is also easy, you just need to return Publisher .emitOn(Infrastructure.getDefaultExecutor
object. ()); Completable completable = uni.convert().with(UniRxConverter
} s.toCompletable());
@GET Single<Optional<String>> single = uni.convert().with(UniRxC
@Path("/stream") public Multi<String> stream() { onverters.toSingle());
@Produces(MediaType.SERVER_SENT_EVENTS) return Multi.createFrom().items("hello", "world") Observable<String> observable = uni.convert().with(UniRxCon
public Publisher<String> publishers() { .emitOn(Infrastructure.getDefaultExecutor verters.toObservable());
return Flowable ()); Flowable<String> flowable = uni.convert().with(UniRxConvert
.interval(500, TimeUnit.MILLISECONDS) } ers.toFlowable());
.map(s -> atomicInteger.getAndIncrement()) } ...
.map(i -> Integer.toString(i));
} Completable completable = multi.convert().with(MultiRxConve
Converting from/to RxJava2 or Reactor APIs: rters.toCompletable());
Single<Optional<String>> single = multi.convert().with(Mult

Mutiny and JAX-RS RxJava 2 iRxConverters.toSingle());


Observable<String> observable = multi.convert().with(MultiR
Apart from the CompletionStage support, there is also support for <dependency> xConverters.toObservable());
Mutiny. <groupId>io.smallrye.reactive</groupId> Flowable<String> flowable = multi.convert().with(MultiRxCon
<artifactId>mutiny-rxjava</artifactId> verters.toFlowable());
</dependency> ...
./mvnw quarkus:add-extension
-Dextensions="quarkus-resteasy-mutiny"

From RxJava2 : Reactor API

<dependency>
<groupId>io.smallrye.reactive</groupId>
<artifactId>mutiny-reactor</artifactId>
</dependency>

From Reactor :
Uni<String> uniFromMono = Uni.createFrom().converter(UniRea
or in Mutiny: @Inject @Stream(“out”)
ctorConverters.fromMono(), mono); Publisher<String> result;
Uni<String> uniFromFlux = Uni.createFrom().converter(UniRea @ApplicationScoped
ctorConverters.fromFlux(), flux); public class ProducerData { @GET
Multi<String> multiFromMono = Multi.createFrom().converter @Outgoing("my-in-memory") @Produces(SERVER_SENT_EVENTS)
(MultiReactorConverters.fromMono(), mono); public Multi<Integer> generate() { public Publisher<String> stream() {
Multi<String> multiFromFlux = Multi.createFrom().converter return Multi.createFrom().ticks().every(Duration.of return result;
(MultiReactorConverters.fromFlux(), flux); Seconds(5)) }
.onItem().apply(n -> random.nextInt(100));
}
}
To Reactor : Message → Business Logic

Mono<String> mono = uni.convert().with(UniReactorConverter @ApplicationScoped


s.toMono());
If you want to dispatch to all subscribers you can annotate the
public class ReceiverMessages {
Flux<String> flux = uni.convert().with(UniReactorConverter
method with @Broadcast .
@Incoming("prices")
s.toFlux()); public void print(String price) {
Consumes generated data from my-in-memory stream.
}
Mono<String> mono2 = multi.convert().with(MultiReactorConve }
rters.toMono()); @ApplicationScoped
Flux<String> flux2 = multi.convert().with(MultiReactorConve public class ConsumerData {
rters.toFlux()); @Incoming("my-in-memory")
public void randomNumber(int randomNumber) { To indicate that the method should be executed on a worker pool
System.out.println("Received " + randomNumber); you can use @Blocking :
}
CompletionStages or Publisher } @Outgoing("Y")
@Incoming("X")
CompletableFuture<String> future = Uni @Blocking
.createFrom().completionStage(CompletableFuture.sup
You can also inject an stream as a eld:
plyAsync(() -> "hello"));

@Inject To customize:
CompletationStage<String> cs = Uni
.createFrom().subscribeAsCompletionStage(); @Stream("my-in-memory") Publisher<Integer> randomRumbers;
@Blocking(value="my-custom-pool", ordered = false)

Multi implements Publisher . @Inject @Stream("generated-price")


Emitter<String> emitter; smallrye.messaging.worker.my-custom-pool.max-concurrency=3
Reactive Messaging
Quarkus relies on MicroPro le Reactive Messaging spec to Patterns Possible implementations are:
implement reactive messaging streams.
REST API → Message In-Memory
mvn quarkus:add-extension
-Dextensions=" If the stream is not con gured then it is assumed to be an in-
@Inject @Stream(“in”)
io.quarkus:quarkus-smallrye-reactive-messaging" memory stream, if not then stream type is de ned by connector
Emitter<String> emitter;
eld.

emitter.send(message);
Kafka
You can just start using in-memory streams by using @Incoming to
produce data and @Outgoing to consume data. To integrate with Kafka you need to add next extensions:
Message → Message
Produce every 5 seconds one piece of data.
mvn quarkus:add-extension
@Incoming(“in”) -Dextensions="
@ApplicationScoped io.quarkus:quarkus-smallrye-reactive-messaging-kafka"
@Outgoing(“out”)
public class ProducerData {
public String process(String in) {

}
@Outgoing("my-in-memory")
Then @Outgoing , @Incoming or @Stream can be used.
public Flowable<Integer> generate() {
return Flowable.interval(5, TimeUnit.SECONDS)
Message → SSE Kafka con guration schema: mp.messaging.[outgoing|incoming].
.map(tick -> random.nextInt(100));
{stream-name}.<property>=<value> .
}
} The connector type is smallrye-kafka .
mp.messaging.outgoing.generated-price.connector= amqp-username=quarkus Kafka Streams
smallrye-kafka amqp-password=quarkus
mp.messaging.outgoing.generated-price.topic= # write Create streaming queries with the Kafka Streams API.
prices mp.messaging.outgoing.generated-price.connector=
mp.messaging.outgoing.generated-price.bootstrap.servers= smallrye-amqp ./mvnw quarkus:add-extension
localhost:9092 mp.messaging.outgoing.generated-price.address= -Dextensions="kafka-streams"
mp.messaging.outgoing.generated-price.value.serializer= prices
org.apache.kafka.common.serialization.IntegerSerializer mp.messaging.outgoing.generated-price.durable=
true
mp.messaging.incoming.prices.connector= # read
All we need to do for that is to declare a CDI producer method
smallrye-kafka mp.messaging.incoming.prices.connector=
which returns the Kafka Streams
org.apache.kafka.streams.Topology :
mp.messaging.incoming.prices.value.deserializer= smallrye-amqp
org.apache.kafka.common.serialization.IntegerDeserializ mp.messaging.incoming.prices.durable=
er true @ApplicationScoped
public class TopologyProducer {
@Produces
public Topology buildTopology() {
A complete list of supported properties are in Kafka site. For the A complete list of supported properties for AMQP.
org.apache.kafka.streams.StreamsBuilder.StreamsBuil
producer and for consumer
der
MQTT
builder = new StreamsBuilder();
JSON-B Serializer/Deserializer
To integrate with MQTT you need to add next extensions: // ...
You can use JSON-B to serialize/deserialize objects. builder.stream()
.join()
./mvnw quarkus:add-extension
// ...
./mvnw quarkus:add-extension -Dextensions="vertx, smallrye-reactive-streams-operator
.toStream()
-Dextensions="quarkus-kafka-client" s
.to();
smallrye-reactive-messaging"
return builder.build();
}
To serialize you can use }
io.quarkus.kafka.client.serialization.JsonbSerializer . And add io.smallrye.reactive:smallrye-reactive-messaging-mqtt-
1.0:0.0.10 dependency in your build tool.
To deserialize you need to extend
io.quarkus.kafka.client.serialization.JsonbDeserializer and Then @Outgoing , @Incoming or @Stream can be used. Previous example produces content to another stream. If you want
provide a type. to write interactive queries, you can use Kafka streams.
MQTT con guration schema: mp.messaging.[outgoing|incoming].
{stream-name}.<property>=<value> . @Inject
public class BeerDeserializer
extends JsonbDeserializer<Beer> { KafkaStreams streams;
The connector type is smallrye-mqtt .

public BeerDeserializer() { return streams
super(Beer.class); mp.messaging.outgoing.topic-price.type= .store("stream", QueryableStoreTypes.keyValueStore
} smallrye-mqtt ());
mp.messaging.outgoing.topic-price.topic=
} prices
mp.messaging.outgoing.topic-price.host=
The Kafka Streams extension is con gured via the Quarkus
localhost
con guration le application.properties .
mp.messaging.outgoing.topic-price.port=
AMQP 1883
quarkus.kafka-streams.bootstrap-servers=localhost:9092
mp.messaging.outgoing.topic-price.auto-generated-client-id=
To integrate with AMQP you need to add next extensions: quarkus.kafka-streams.application-id=temperature-aggregator
true
quarkus.kafka-streams.application-server=${hostname}:8080

./mvnw quarkus:add-extension quarkus.kafka-streams.topics=weather-stations,temperature-v
mp.messaging.incoming.prices.type=
-Dextensions="reactive-messaging-amqp" alues
smallrye-mqtt

mp.messaging.incoming.prices.topic=
kafka-streams.cache.max.bytes.buffering=10240
prices
kafka-streams.commit.interval.ms=1000
Then @Outgoing , @Incoming or @Stream can be used. mp.messaging.incoming.prices.host=
localhost
AMQP con guration schema: mp.messaging.[outgoing|incoming]. mp.messaging.incoming.prices.port=
{stream-name}.<property>=<value> . Special properties amqp-username 1883 IMPORTANT: All the properties within the kafka-streams
and amqp-password are used to con gure AMQP broker credentials. 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.
The connector type is smallrye-amqp .
Reactive DataSource Properties
Common Reeactive DataSource Client con guration properties Database con guration is the same as shown in Persistence Reactive Transactions
pre xed with quarkus.datasource : section, but URL is different as it is not a jdbc.
io.vertx.mutiny.sqlclient.SqlClientHelper is an util class that
reactive.cache-prepared-statements
quarkus.datasource.db-kind=postgresql allows you to run reactive persisten code within a transaction.
Prepared statements should be cached on the client side. quarkus.datasource.reactive.url=postgresql:///your_database
(default: false )
Uni<Void> r = SqlClientHelper.inTransactionUni(client, tx -
> {
reactive.url
Then you can inject io.vertx.mutiny.pgclient.PgPool class. Uni<RowSet<Row>> insertOne = tx.preparedQuery("INSE
The datasource URL. RT INTO fruits (name) VALUES ($1) RETURNING (id)")
@Inject .execute(Tuple.of(fruit1.name));
reactive.max-size });
PgPool client;
The datasource pool maximum size.
Uni<List<Fruit>> fruits =
reactive.trust-all client.preparedQuery("SELECT * FROM fruits")
ActiveMQ Artemis
All server certi cates should be trusted. (default: false ) .onItem().apply(rowSet -> {
JsonArray jsonArray = new JsonArray();
Quarkus uses Reactive Messaging to integrate with messaging
for (Row row : rowSet) {
reactive.trust-certificate-pem systems, but in case you need deeper control when using Apache
jsonArray.add(from(row));
Trust con guration in the PEM format. ActiveMQ Artemis there is also an extension:
}
return jsonArray;
reactive.trust-certificate-jks ./mvnw quarkus:add-extension
})
Trust con guration in the JKS format. -Dextensions="quarkus-artemis-core"

reactive.trust-certificate-pfx
Trust con guration in the PFX format.
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.
reactive.key-certificate-pem
database in a reactive way, instead of using JDBC.
Key/cert con guration in the PEM format.
@ApplicationScoped
./mvnw quarkus:add-extension
reactive.key-certificate-jks public class ArtemisConsumerManager {
-Dextensions="quarkus-reactive-mysql-client"

Key/cert con guration in the JKS format.
@Inject
ServerLocator serverLocator;
reactive.key-certificate-pfx
Database con guration is the same as shown in Persistence
Key/cert con guration in the PFX format. section, but URL is different as it is not a jdbc. private ClientSessionFactory connection;

reactive.thread-local @PostConstruct
quarkus.datasource.db-kind=mysql
Use one connection pool per thread. quarkus.datasource.reactive.url=mysql:///your_database public void init() throws Exception {
connection = serverLocator.createSessionFactory();
reactive.reconnect-attempts }
}
The number of reconnection attempts when a pooled connection Then you can inject io.vertx.mutiny.mysqlclient.MySQLPool class.
cannot be established on rst try. (default: 0 )
Reactive DB2 Client And con gure ServerLocator in application.properties :
reactive.reconnect-interval
The interval between reconnection attempts when a pooled You can use Reactive DB2 to execute queries to DB2 database in a
connection cannot be established on rst try. (default: PT1S ) reactive way, instead of using JDBC. quarkus.artemis.url=tcp://localhost:61616

reactive.idle-timeout
./mvnw quarkus:add-extension
The maximum time without data written to or read from a -Dextensions="quarkus-reactive-db2-client" You can con gure ActiveMQ Artemis in application.properties le
connection before it is removed from the pool. by using next properties pre xed with quarkus :

Reactive PostgreSQL Client Database con guration is the same as shown in Persistence
artemis.url

Connection URL.
section, but URL is different as it is not a jdbc.
You can use Reactive PostgreSQL to execute queries to PostreSQL
database in a reactive way, instead of using JDBC way. artemis.username
quarkus.datasource.db-kind=db2
quarkus.datasource.reactive.url=vertx-reactive:db2://localh
Username for authentication.
./mvnw quarkus:add-extension ost:50005/hreact
-Dextensions="quarkus-reactive-pg-client" artemis.password
Password for authentication.
Then you can inject i i db2 li 2 l class
Artemis JMS Example of Vert.X Web Client:
quarkus.sqs.sync-client.type=apache

If you want to use JMS with Artemis, you can do it by using its
@Inject
extension:
Vertx vertx;
You can go async by using Mutiny:

./mvnw quarkus:add-extension private WebClient client;
-Dextensions="quarkus-artemis-jms" @Inject
@PostConstruct software.amazon.awssdk.services.sqs.SqsAsyncClient sqs;
void initialize() {
this.client = WebClient.create(vertx, ...); Uni.createFrom()
And then you can inject javax.jms.ConnectionFactory :
} .completionStage(
sqs.sendMessage(m -> m.queueUrl(queueUrl).messageBo
@ApplicationScoped dy(message))
public class ArtemisConsumerManager { )
Amazon SQS Client .onItem()...
@Inject
ConnectionFactory connectionFactory; return Uni.createFrom()
./mvnw quarkus:add-extension
.completionStage(
private Connection connection; -Dextensions="amazon-sqs"
sqs.receiveMessage(m -> m.maxNumberOfMessages(10).q
ueueUrl(queueUrl))
@PostConstruct )
public void init() throws JMSException { Injecting the client: .onItem()
connection = connectionFactory.createConnection();
connection.start();
@Inject
}
software.amazon.awssdk.services.sqs.SqsClient sqs; And you need to add the asynchronous Netty client:
}

SendMessageResponse response = sqs.sendMessage(m -> m.queue
<dependency>
Url(queueUrl).messageBody(message));
<groupId>software.amazon.awssdk</groupId>

Con guration options are the same as Artemis core. List<Message> messages = sqs.receiveMessage(m -> m.maxNumbe
<artifactId>netty-nio-client</artifactId>
</dependency>
rOfMessages(10).queueUrl(queueUrl)).messages();

Vert.X Reactive Clients


And con gure it: Con guration properties are the same as Amazon DynamoDB but
Vert.X Reactive clients in Quarkus, the next clients are supported
changing the pre x from dynamodb to sqs .
and you need to add the dependency to use them:
quarkus.sqs.endpoint-override=http://localhost:8010
Vert.X Mail Client quarkus.sqs.aws.region=us-east-1
io.smallrye.reactive:smallrye-mutiny-vertx-mail-client quarkus.sqs.aws.credentials.type=static
quarkus.sqs.aws.credentials.static-provider.access-key-id=t
Vert.X MongoDB Client est-key
io.smallrye.reactive:smallrye-mutiny-vertx-mongo-client
quarkus.sqs.aws.credentials.static-provider.secret-access-k
ey=test-secret

Vert.X Redis Client


io.smallrye.reactive:smallrye-mutiny-vertx-redis-client
You need to set a HTTP client either URL Connection :
Vert.X Cassandra Client
io.smallrye.reactive:smallrye-mutiny-vertx-cassandra-client <dependency>
<groupId>software.amazon.awssdk</groupId>
Vert.X Consul Client <artifactId>url-connection-client</artifactId>
</dependency>
io.smallrye.reactive:smallrye-mutiny-vertx-consul-client

Vert.X Kafka Client


or Apache HTTP:
io.smallrye.reactive:smallrye-mutiny-vertx-kafka-client

Vert.X AMQP Client <dependency>


<groupId>software.amazon.awssdk</groupId>
io.smallrye.reactive:smallrye-mutiny-vertx-amqp-client
<artifactId>apache-client</artifactId>
</dependency>
Vert.X RabbitMQ Client
io.smallrye.reactive:smallrye-mutiny-vertx-rabbitmq-client
RBAC You need to provide permissions set by using the roles-allowed
@Inject
JsonWebToken jwt;
property or use the built-in ones deny , permit or authenticated .
You can set RBAC using annotations or in application.properties .
You can use enabled property (ie @Inject
Annotations @Claim(standard = Claims.preferred_username)
quarkus.http.auth.permission.permit1.enabled ) to enable the entire
permission set. String name;
You can de ne roles by using
javax.annotation.security.RolesAllowed annotation.
Testing @Inject
@Claim("groups")
@RolesAllowed("Subscriber") Quarkus provides explicit support for testing with different users, Set<String> groups;
and with the security subsystem disabled.
@Inject
You can use io.quarkus.security.Authenticated as a shortcut of <dependency> JWTParser parser;
@RolesAllowed("*") . <groupId>io.quarkus</groupId>
<artifactId>quarkus-test-security</artifactId>
To alter RBAC behaviour there are two con guration properties: <scope>test</scope> Set of supported types: String , Set<String> , Long , Boolean,
</dependency> `javax.json.JsonValue , Optional ,
quarkus.security.deny-unannotated=true org.eclipse.microprofile.jwt.ClaimValue .

And con guration in src/main/resources/application.properties :


@Test
Con guration options: @TestSecurity(authorizationEnabled = false)
mp.jwt.verify.publickey.location=
void someTestMethod() {
quarkus.jaxrs.deny-uncovered META-INF/resources/publicKey.pem
...
mp.jwt.verify.issuer=
If true denies by default to all JAX-RS endpoints. (default: false ) }
https://quarkus.io/using-jwt-rbac

quarkus.security.deny-unannotated @Test
If true denies by default all CDI methods and JAX-RS endpoints. @TestSecurity(user = "testUser", roles = {"admin", "user"})
void someTestMethod() { Con guration options:
(default: false )
...
} mp.jwt.verify.publickey
By default in Quarkus, if an incoming request has a credential the
request will always be authenticated (even if the target page does Public Key text itself to be supplied as a string.
not require authentication).
mp.jwt.verify.publickey.location Relative path or URL of a public
You can change this behaviour by setting
BouncyCastle key.
quarkus.http.auth.proactive property to false .
Quarkus supports BouncyCastle, you only need to add the mp.jwt.verify.issuer
File Con guration BouncyCastle dependency and con gure the security provider: iss accepted as valid.

De ning RBAC in application.properties instead of using quarkus.security.security-providers=BC smallrye.jwt.token.header


annotations. quarkus.security.security-providers=BCJSSE
Sets header such as Cookie is used to pass the token. (default:
Authorization ).
quarkus.http.auth.policy.role-policy1.roles-allowed=
user,admin
quarkus.http.auth.permission.roles1.paths=
JWT smallrye.jwt.token.cookie

/roles-secured/*,/other/*,/api/* Name of the cookie containing a token.


quarkus.http.auth.permission.roles1.policy= Quarkus implements MicroPro le JWT RBAC spec.
role-policy1 smallrye.jwt.token.schemes
mvn quarkus:add-extension Comma-separated list containing an alternative single or multiple
quarkus.http.auth.permission.permit1.paths= -Dextensions="io.quarkus:quarkus-smallrye-jwt" schemes. (default: Bearer ).
/public/*
quarkus.http.auth.permission.permit1.policy= smallrye.jwt.require.named-principal
permit A token must have a upn or preferred_username or sub claim set
Minimum JWT required claims: typ , alg , kid , iss , sub , exp , iat ,
quarkus.http.auth.permission.permit1.methods= if using java.security.Principal . True makes throw an exception
jti , upn , groups .
GET if not set. (default: false ).
You can inject token by using JsonWebToken or a claim individually by
quarkus.http.auth.permission.deny1.paths= using @Claim . smallrye.jwt.path.sub
/forbidden
quarkus.http.auth.permission.deny1.policy= Path to the claim with subject name.
deny
smallrye.jwt.claims.sub
Default sub claim value.
smallrye.jwt.path.groups
@Inject @GET
Path to the claim containing the groups. @Claim(standard = Claims.iat) @RolesAllowed("admin")
private Instance<Long> providerIAT;
smallrye.jwt.groups-separator
Separator for splitting a string which may contain multiple group Con gure application to Keycloak service in application.properties
values. (default. ` `). RBAC le.

smallrye.jwt.claims.groups JWT groups claim is directly mapped to roles to be used in security quarkus.oidc.realm=quarkus
Default groups claim value. annotations. quarkus.oidc.auth-server-url=http://localhost:8180/auth
quarkus.oidc.resource=backend-service
smallrye.jwt.jwks.refresh-interval @RolesAllowed("Subscriber") quarkus.oidc.bearer-only=true
JWK cache refresh interval in minutes. (default: 60 ). quarkus.oidc.credentials.secret=secret

smallrye.jwt.expiration.grace Generate tokens


Expiration grace in seconds. (default: 60 ). Con guration options with quarkus.oidc pre x:
JWT generation API:
enabled
smallrye.jwt.verify.aud
Comma separated list of the audiences that a token aud claim
Jwt.claims() The OIDC is enabled. (default: true )
.issuer("https://server.com")
may contain.
.claim("customClaim", 3) tenant-enabled
.sign(createKey());
smallrye.jwt.verify.algorithm If the tenant con guration is enabled. (default: true )

Signature algorith. (defsult: RS256 ) JwtSignatureBuilder jwtSignatureBuilder = Jwt.claims("/test
application-type
JsonToken.json").jws();
smallrye.jwt.token.kid jwtSignatureBuilder The application type. Possible values: web_app , service . (default:
service )
If set then the veri cation JWK key as well every JWT token must .signatureKeyId("some-key-id")
have a matching kid header. .signatureAlgorithm(SignatureAlgorithm.ES256)
.header("custom-header", "custom-value"); connection-delay
smallrye.jwt.time-to-live .sign(createKey()); The maximum amount of time the adapter will try connecting.

The maximum number of seconds that a JWT may be issued for
Jwt.claims("/testJsonToken.json")
use. auth-server-url
.encrypt(createKey());
The base URL of the OpenID Connect (OIDC) server.

smallrye.jwt.sign.key-location
JwtEncryptionBuilder jwtEncryptionBuilder = Jwt.claims("/te
Location of a private key which will be used to sign the claims stJsonToken.json").jwe();
introspection-path
when either a no-argument sign() or innerSign() method is jwtEncryptionBuilder Relative path of the RFC7662 introspection service.
called. .keyEncryptionKeyId("some-key-id")
.keyEncryptionAlgorithm(KeyEncryptionAlgorithm.ECDH_E jwks-path
smallrye.jwt.encrypt.key-location S_A256KW) Relative path of the OIDC service returning a JWK set.
Location of a public key which will be used to encrypt the claims .header("custom-header", "custom-value");
or inner JWT when a no-argument encrypt() method is called. .encrypt(createKey()); public-key

Public key for the local JWT token veri cation
Supported public key formats: Jwt.claims("/testJsonToken.json")
.innerSign(createKey());
client-id
PKCS#8 PEM .encrypt(createKey());
The client-id of the application.
JWK
roles.role-claim-path
JWKS OpenId Connect Path to the claim containing an array of groups. ( realm/groups )
JWK Base64 URL Quarkus can use OpenId Connect or OAuth 2.0 authorization
roles.role-claim-separator
servers such as Keycloak to protect resources using bearer token
JWKS Base64 URL issued by Keycloak server. Separator for splitting a string which may contain multiple group
values.
To send a token to server-side you should use Authorization
header: curl -H "Authorization: Bearer eyJraWQiOi… " . mvn quarkus:add-extension
token.issuer
-Dextensions="using-openid-connect"
To inject claim values, the bean must be @RequestScoped CDI Issuer claim value.
scoped. If you need to inject claim values in scope with a lifetime
greater than @RequestScoped then you need to use You can also protect resources with security annotations.
token.audience
javax.enterprise.inject.Instance interface. Audience claim value.

t k i ti
Expiration grace period in seconds. You can use quarkus.http.cors property to enable URL used to validate the token and gather the authentication
consuming form different domain. claims.
token.principal-claim
Name of the claim which contains a principal name. Multi-tenancy quarkus.oauth2.role-claim
The claim that is used in the endpoint response to load the roles
Multi-tenancy is supported by adding a sub-category to OIDC ((default: scope )
token.refresh-expired
con guration properties (ie quarkus.oidc.{tenent_id}.property ).
If property is enabled then a refresh token request is performed.
quarkus.oidc.auth-server-url=http://localhost:8180/auth/rea
Authenticating via HTTP
credentials.secret
lms/quarkus
The client secret HTTP basic auth is enabled by the quarkus.http.auth.basic=true
quarkus.oidc.client-id=multi-tenant-client
property.
quarkus.oidc.application-type=web-app
authentication.redirect-path
HTTP form auth is enabled by the
Relative path for calculating a redirect_uri query parameter. quarkus.oidc.tenant-b.auth-server-url=https://accounts.goog
quarkus.http.auth.form.enabled=true property.
le.com
authentication.restore-path-after-redirect quarkus.oidc.tenant-b.application-type=web-app Then you need to add elytron-security-properties-file or elytron-
quarkus.oidc.tenant-b.client-id=xxxx security-jdbc .
The original request URI used before the authentication will be
quarkus.oidc.tenant-b.credentials.secret=yyyy
restored after the user has been redirected back to the
application. (default: true )
quarkus.oidc.tenant-b.token.issuer=https://accounts.google.
Security with Properties File
com
quarkus.oidc.tenant-b.authentication.scopes=email,profile,o
authentication.scopes You can also protect endpoints and store identities (user, roles) in
penid
List of scopes. the le system.

authentication.extra-params mvn quarkus:add-extension


Additional properties which will be added as the query OAuth2 -Dextensions="elytron-security-properties-file"
parameters .
Quarkus integrates with OAuth2 to be used in case of opaque
tokens (none JWT) and its validation against an introspection
authentication.cookie-path You need to con gure the extension with users and roles les:
endpoint.
Cookie path parameter.
And con guration in src/main/resources/application.properties :
mvn quarkus:add-extension
proxy.host
-Dextensions="security-oauth2" quarkus.security.users.file.enabled=true
The host (name or IP address) of the Proxy.
quarkus.security.users.file.users=test-users.properties
quarkus.security.users.file.roles=test-roles.properties
proxy.port
And con guration in src/main/resources/application.properties : quarkus.security.users.file.auth-mechanism=BASIC
The port number of the Proxy. (default: 80 ) quarkus.security.users.file.realm-name=MyRealm
quarkus.security.users.file.plain-text=true
quarkus.oauth2.client-id=client_id
proxy.username
quarkus.oauth2.client-secret=secret
The username to authenticate. quarkus.oauth2.introspection-url=http://oauth-server/intros
pect Then users.properties and roles.properties :
proxy.password

The password to authenticate. scott=jb0ss


And you can map roles to be used in security annotations. jdoe=p4ssw0rd
end-session-path

Relative path of the OIDC end_session_endpoint . @RolesAllowed("Subscriber")

logout.path
scott=Admin,admin,Tester,user
jdoe=NoRolesUser
The relative path of the logout endpoint at the application. Con guration options:
logout.post-logout-path quarkus.oauth2.enabled
IMPORTANT: If plain-text is set to false (or omitted) then
Relative path of the application endpoint where the user should Determine if the OAuth2 extension is enabled. (default: true ) passwords must be stored in the form MD5
be redirected to after logging out.
( username :`realm`:`password`).
quarkus.oauth2.client-id
tls.verification Elytron File Properties con guration properties. Pre x
The OAuth2 client id used to validate the token.
Sets the TLs veri cation. Possible values: REQUIRED , NONE . quarkus.security.users is skipped.
(default: REQUIRED ). quarkus.oauth2.client-secret
file.enabled
The OAuth2 client secret used to validate the token.
With Keycloak OIDC server The le realm is enabled. (default: false )
https://host:port/auth/realms/{realm} where {realm} has
quarkus.oauth2.introspection-url
to be replaced by the name of the Keycloak realm file auth-mechanism
The authentication mechanism. ( default: BASIC ) You can also protect endpoints and store identities in a database. principal-query.bcrypt-password-mapper.hash-encoding
A string referencing the password hash encoding ( BASE64 or HEX ).
file.realm-name mvn quarkus:add-extension (default: BASE64 )
The authentication realm name. (default: Quarkus ) -Dextensions="elytron-security-jdbc"
principal-query.bcrypt-password-mapper.salt-index
file.plain-text The index column containing the Bcrypt salt. (default: 0 )
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-encoding
file.users You need to con gure JDBC and Elytron JDBC Realm: A string referencing the salt encoding ( BASE64 or HEX ). (default:
Classpath resource of user/password. (default: BASE64 )
users.properties ) quarkus.datasource.url=
quarkus.datasource.driver=org.h2.Driver principal-query.bcrypt-password-mapper.iteration-count-index
quarkus.datasource.username=sa
file.roles The index column containing the Bcrypt iteration count. (default:
quarkus.datasource.password=sa
Classpath resource of user/role. (default: roles.properties ) 0)

quarkus.security.jdbc.enabled=true
Embedded Realm For multiple datasources you can use the datasource name in the
quarkus.security.jdbc.principal-query.sql=
properties:
SELECT u.password, u.role FROM test_user u WHERE u.user
You can embed user/password/role in the same
=?
application.properties :
quarkus.security.jdbc.principal-query quarkus.datasource.url=
.clear-password-mapper.enabled=true quarkus.security.jdbc.principal-query.sql=
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.permissions.url=
quarkus.security.users.embedded.users.scott=jb0ss quarkus.security.jdbc.principal-query quarkus.security.jdbc.principal-query.permissions.sql=
quarkus.security.users.embedded.roles.scott=admin,tester,us .attribute-mappings.0.index=2
er quarkus.security.jdbc.principal-query
quarkus.security.users.embedded.auth-mechanism=BASIC .attribute-mappings.0.to=groups
Security with JPA
You can also protect endpoints and store identities in a database
IMPORTANT: If plain-text is set to false (or omitted) then You need to set the index (1-based) of password and role. using JPA.
passwords must be stored in the form MD5
( username :`realm`:`password`). Elytron JDBC Realm con guration properties. Pre x
mvn quarkus:add-extension
quarkus.security.jdbc is skipped.
Pre x quarkus.security.users.embedded is skipped. -Dextensions="security-jpa"
auth-mechanism
algorithm
The authentication mechanism. (default: BASIC )
Determine which algorithm to use. Possible values: DIGEST_MD5 ,
Also you might require jdbc-postgresql , resteasy ,
DIGEST_SHA , DIGEST_SHA_256 , DIGEST_SHA_384 , DIGEST_SHA_512 ,
realm-name hibernate-orm-panache .
DIGEST_SHA_512_256 . (default: DIGEST_MD5 )
The authentication realm name. (default: Quarkus )
file.enabled
enabled
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
Th i d f l t i i dh h (d f lt )
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 sensitive data.
@Entity 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-path.singer=
realm-name multi/singer

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/singer 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
Vault con guration properties. Pre x quarkus.vault is skipped.
@Inject @Inject
VaultKVSecretEngine kvSecretEngine; VaultTransitSecretEngine transit;
url

kvSecretEngine.readSecret("myapps/vault-quickstart/" + vaul transit.encrypt("my_encryption", text); Vault server URL
tPath).toString(); transit.decrypt("my_encryption", text).asString();
transit.sign("my-sign-key", text); authentication.client-token
Map<String, String> secrets; Vault token to access
kvSecretEngine.writeSecret("myapps/vault-quickstart/crud",
secrets); authentication.app-role.role-id
Vault TOTP

Role Id for AppRole auth
kvSecretEngine.deleteSecret("myapps/vault-quickstart/crud" TOTP secret engine is supported by using
); io.quarkus.vault.VaultTOTPSecretEngine class: authentication.app-role.secret-id
Secret Id for AppRole auth
@Inject
Fetching credentials DB VaultTOTPSecretEngine vaultTOTPSecretEngine; authentication.app-role.secret-id-wrapping-token

With the next kv vault kv put secret/myapps/vault-quickstart/db Wrapping token containing a Secret Id. secret-id and secret-id-
CreateKeyParameters createKeyParameters = new CreateKeyPara
password=connor wrapping-token are exclusive.
meters("Google", "[email protected]");
createKeyParameters.setPeriod("30m");
authentication.userpass.username
quarkus.vault.credentials-provider.mydatabase.kv-path=
myapps/vault-quickstart/db /** Generate Key (QR code) */ Username for userpass auth
final Optional<KeyDefinition> myKey = vaultTOTPSecretEngine
quarkus.datasource.db-kind= .createKey("my_ authentication.userpass.password
postgresql key_2", createKeyParameters); Password for userpass auth
quarkus.datasource.username=
sarah /** Generate key number to login */ authentication.userpass.password-wrapping-token
quarkus.datasource.credentials-provider= final String keyCode = vaultTOTPSecretEngine.generateCode(
Wrapping token containing a password. password and password-
mydatabase "my_key_2");
wrapping-token are exclusive.
quarkus.datasource.jdbc.url=
jdbc:postgresql://localhost:5432/mydatabase /** Login logic */
authentication.kubernetes.role
boolean valid = vaultTOTPSecretEngine.validateCode("my_key_
2", keyCode); Kubernetes authentication role
No password is set as it is fetched from Vault.
authentication.kubernetes.jwt-token-path

Dynamic credentials are also supported: Vault Provisioning Location of the le containing the Kubernetes JWT token

Running the following dynamic database con g in Vault: Vault extension offers façade classes to Vault provisioning renew-grace-period
functions: Renew grace period duration (default: 1H )
vault write database/config/mydb plugin_name=postgresql-database-
plugin …
..
@Inject secret-config-cache-period
You can con gure as: VaultSystemBackendEngine vaultSystemBackendEngine; Vault con g source cache period (default: 10M )

@Inject
quarkus.vault.credentials-provider secret-config-kv-path
VaultKubernetesAuthService vaultKubernetesAuthService;
.mydatabase.database-credentials-role=mydbrole
Vault path in kv store. List of paths is supported in CSV

String rules = "path \"transit/*\" {\n" +
quarkus.datasource.db-kind= log-confidentiality-level
" capabilities = [ \"create\", \"read\", \"updat
postgresql
e\" ]\n" + Used to hide con dential infos. low , medium , high (default:
quarkus.datasource.credentials-provider=
"}"; medium )
mydatabase
String policyName = "sys-test-policy";
quarkus.datasource.jdbc.url=
kv-secret-engine-version
jdbc:postgresql://localhost:5432/mydatabase
vaultSystemBackendEngine.createUpdatePolicy(policyName, rul Kv secret engine version (default: 1)
es);

kv-secret-engine-mount-path Kv secret engine path (default: secret )
Username and password are fetched from Vault vaultKubernetesAuthService
.createRole(roleName, new VaultKubernetesAuthRole() tls.skip-verify
Transit .setBoundServiceAccountNames(boundServiceAccountN
Allows to bypass certi cate validation on TLS communications
ames)
(default: false )
.setBoundServiceAccountNamespaces(boundServiceAcc
ountNamespaces)
tls.ca-cert
.setTokenPolicies(tokenPolicies));
Certi cate bundle used to validate TLS communications
tls.use-kubernetes-ca-cert
quarkus.sqs.sync-client.type=apache @Inject
TLS will be active (default: true ) IamClient client;

connect-timeout @Inject
You can go async by using Mutiny:
Tiemout to establish a connection (default: 5S ) IamAsyncClient async;

@Inject
read-timeout
software.amazon.awssdk.services.kms.KmsAsyncClient kms;
Request timeout (default: 1S ) quarkus.iam.endpoint-override=${iam.url}
Uni.createFrom().completionStage( quarkus.iam.aws.region=us-east-1
credentials-provider."credentials-provider".database-credentials- kms.encrypt(req -> req.keyId(keyArn).plaintext(SdkByte quarkus.iam.aws.credentials.type=static
role s.fromUtf8String(data)) quarkus.iam.aws.credentials.static-provider.access-key-id=t
Database credentials role )) est-key
quarkus.iam.aws.credentials.static-provider.secret-access-k
credentials-provider."credentials-provider".kv-path ey=test-secret

A path in vault kv store, where we will nd the kv-key And you need to add the asynchronous Netty client:

credentials-provider."credentials-provider".kv-key <dependency> Con guration properties are the same as Amazon DynamoDB but
Key name to search in vault path kv-path (default: password ) <groupId>software.amazon.awssdk</groupId> changing the pre x from dynamodb to iam .
<artifactId>netty-nio-client</artifactId>

Amazon KMS </dependency>

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

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

You need to set a HTTP client either URL Connection :

quarkus.kms.endpoint-override=http://localhost:8011 <dependency>
quarkus.kms.aws.region=us-east-1 <groupId>software.amazon.awssdk</groupId>
quarkus.kms.aws.credentials.type=static <artifactId>url-connection-client</artifactId>
quarkus.kms.aws.credentials.static-provider.access-key-id=t </dependency>
est-key
quarkus.kms.aws.credentials.static-provider.secret-access-k
ey=test-secret
or Apache HTTP:

<dependency>
You need to set a HTTP client either URL Connection : <groupId>software.amazon.awssdk</groupId>
<artifactId>apache-client</artifactId>
<dependency> </dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>url-connection-client</artifactId>
</dependency>
And you need to add the asynchronous Netty client:

<dependency>
or Apache HTTP: <groupId>software.amazon.awssdk</groupId>
<artifactId>netty-nio-client</artifactId>
<dependency> </dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>apache-client</artifactId>
</dependency>
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

@Produces(MediaType.APPLICATION_JSON) You can use @Route annotation to use reactive routes and GraphQL
@org.jboss.resteasy.annotations.cache.Cache( @RouteFilter to sue reactive lters in a declarative way:
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) {
handshake-timeout
To consume the service:
CountDownLatch latch = new CountDownLatch(1);
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 /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
fallbackMethod must 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
groups:
"status": "UP", quarkus.smallrye-health.liveness-path=/customlive
"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 /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 /health/live or /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: /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: /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. binder.system
Stackdriver registry con guration properties in Map<String,
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.
<dependency> Native Executable
<groupId>io.opentracing.contrib</groupId>
Jaeger tracer con guration:
<artifactId>opentracing-kafka-client<</artifactId> You can build a native image by using GraalVM. The common use
</dependency> case is creating a Docker image so you can execute the next
quarkus.jaeger.service-name=myservice commands:
quarkus.jaeger.sampler-type=const
quarkus.jaeger.sampler-param=1
quarkus.jaeger.endpoint=http://localhost:14268/api/traces And con gure it: ./mvnw package -Pnative -Dquarkus.native.container-build=tr
ue
quarkus.jaeger.metrics.enabled=true

...
docker build -f src/main/docker/Dockerfile.native
mp.messaging.outgoing.generated-price.topic=prices
-t quarkus/getting-started .

@Traced annotation can be set to disable tracing at class or method docker run -i --rm -p 8080:8080 quarkus/getting-started
# For Produces
level.
mp.messaging.outgoing.generated-price.interceptor.classes=i
Tracer class can be injected into the class.
o.opentracing.contrib.kafka.TracingProducerInterceptor
... You can use quarkus.native.container-runtime to select the
# For consumers container runtime to use. Now docker (default) and podman are the
@Inject
mp.messaging.incoming.prices.interceptor.classes=io.opentra valid options.
Tracer tracer;
cing.contrib.kafka.TracingConsumerInterceptor

tracer.activeSpan().setBaggageItem("key", "value"); ./mvnw package -Pnative -Dquarkus.native.container-runtime=
podman
AWS XRay
You can disable Jaeger extension by using quarkus.jaeger.enabled If you are building native images, and want to use AWS X-Ray
property. To con gure native application, you can create a config directory at
Tracing with your lambda you will need to include quarkus-amazon- the same place as the native le and place an
lambda-xray as a dependency in your pom.
You can log the traceId , spanId and sampled in normal log: application.properties le inside. config/application.properties .

SSL
quarkus.log.console.format=%d{HH:mm:ss} %-5p traceId=%X{tra
ceId}, To create a native image with SSL you need to copy SunEC library
spanId=%X{spanId}, sampled 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

Kafka Tracer

Adds a span for each message sent to or received from a Kafka


topic.
password Path to the JVM Docker le. (default:
FROM quay.io/quarkus/ubi-quarkus-native-image:{graalvm-vers
The registry password. ${project.root}/src/main/docker/Dockerfile.jvm )
ion}-java11 as nativebuilder
RUN mkdir -p /tmp/ssl-libs/lib \
insecure dockerfile-native-path
&& cp /opt/graalvm/lib/security/cacerts /tmp/ssl-libs \
&& cp /opt/graalvm/lib/libsunec.so /tmp/ssl-libs/lib/ Flag to allow insecure registries. (default: false ) Path to the native Docker le. (default:
${project.root}/src/main/docker/Dockerfile.native )
FROM registry.access.redhat.com/ubi8/ubi-minimal build
WORKDIR /work/ S2I
Boolean to set if image should be built. (default: false )
COPY --from=nativebuilder /tmp/ssl-libs/ /work/
COPY target/*-runner /work/application ./mvnw quarkus:add-extensions
push
RUN chmod 775 /work /work/application -Dextensions="quarkus-container-image-s2i"
EXPOSE 8080 Boolean to set if image should be pushed. (default: false )
CMD ["./application", "-Dquarkus.http.host=0.0.0.0", "-Djav
a.library.path=/work/lib", "-Djavax.net.ssl.trustStore=/wor Jib
k/cacerts"] Pre x is quarkus.container-image-docker :
./mvnw quarkus:add-extensions base-jvm-image
-Dextensions="quarkus-container-image-jib"
The base image to use for the s2i build. (default: fabric8/java-
Inclusion of resources alpine-openjdk8-jre )

By default, no resources are included in native executable. Quarkus copies any le under src/main/jib into the built container base-native-image
quarkus.native.resources.includes allows to set glob expressions to
image.
include resources based on src/main/resources path. The base image to use for the native build. (default:
registry.access.redhat.com/ubi8/ubi-minimal )
Pre x is quarkus.container-image-jib :
Given src/main/resources/foo/selected.png :
base-jvm-image Kubernetes
quarkus.native.resources.includes=foo/** The base image to use for the jib build. (default: fabric8/java-
alpine-openjdk8-jre ) Quarks can use Dekorate to generate Kubernetes resources.

Container Images Creation base-native-image ./mvnw quarkus:add-extensions


The base image to use for the native build. (default: -Dextensions="quarkus-kubernetes"
You can levarage to Quarkus to generation and release of Docker registry.access.redhat.com/ubi8/ubi-minimal )
containers. It provides several extensions to make it so.
jvm-arguments Running ./mvnw package the Kubernetes resources are created at
mvn clean package The arguments to pass to java. (default: - target/kubernetes/ directory.
-Dquarkus.container-image.build=true Dquarkus.http.host=0.0.0.0,-
-Dquarkus.container-image.push=true Djava.util.logging.manager=org.jboss.logmanager.LogManager ) Container Images Creation integrates with Kubernetes
-Dquarkus.container-image.registry=quay.io extension, so no need of extra Kubernetes properties.
native-arguments

The arguments to pass to the native application. (default: -


Generated resource is integrated with MicroPro le Health
Dquarkus.http.host=0.0.0.0 )
annotations.
Pre x is quarkus.container-image :
Also, you can customize the generated resource by setting the new
group environment-variables
values in application.properties :
The group/repository of the image. (default: the ${user.name} ) Map of environment variables.

name jvm-entrypoint
The name of the image. (default: the application name) A custom entry point of the container image in JVM mode.

tag native-entrypoint

The tag of the image. (default: the application version) A custom entry point of the container image in native mode.

additional-tags Docker
Additional tags of the container image.
./mvnw quarkus:add-extensions
registry -Dextensions="quarkus-container-image-docker"

The registry to use for pushing. (default: docker.io )

username Pre x is quarkus.container-image-s2i :


The registry username.
dockerfile-jvm-path
quarkus.kubernetes.namespace=mynamespace
Or add new labels and/or annotations: To override the name of the generated resource you can use:
quarkus.kubernetes.name , quarkus.openshift.name and

quarkus.kubernetes.labels.foo=bar quarkus.knative.name .
quarkus.kubernetes.replicas=3
quarkus.kubernetes.annotations.foo=bar
Deployment
quarkus.kubernetes.labels.foo=bar
To deploy automatically the generated resources, you need to set
quarkus.kubernetes.readiness-probe.period-seconds=45 metrics quarkus.container.deploy ag to true .

quarkus.kubernetes.mounts.github-token.path=/deployment/git When using metrics extension, Prometheus annotations are
mvn clean package -Dquarkus.kubernetes.deploy=true
hub generated:
quarkus.kubernetes.mounts.github-token.read-only=true

prometheus.io/scrape: "true"
quarkus.kubernetes.secret-volumes.github-token.volume-name=
prometheus.io/path: /metrics If you set this ag to true , the build and push ags from
github-token
prometheus.io/port: "8080" container-image are set to true too.
quarkus.kubernetes.secret-volumes.github-token.secret-name=
greeting-security To deploy the application, the extension uses the
quarkus.kubernetes.secret-volumes.github-token.default-mode https://github.com/fabric8io/kubernetes-client. All options
=420 Kubernetes Deployment Targets described at Kubernetes Client are valid here.

You can generate different resources setting the property
quarkus.kubernetes.config-map-volumes.github-token.config-m
quarkus.kubernetes.deployment-target .
Minikube
ap-name=my-secret

Possible values are kubernetes , openshift and knative . The default Quarkus has a Minikube extension which creates Kubernetes
quarkus.kubernetes.expose=true
value is kubernetes . manifests that are tailored for Minikube.

quarkus.kubernetes.env.vars.my-env-var=foobar
Knative Properties ./mvnw quarkus:add-extension
quarkus.kubernetes.env.configmaps=my-config-map,another-con
fig-map -Dextensions="minikube"
Most of the Kubernetes properties are valid in Knative output by
quarkus.kubernetes.env.secrets=my-secret,my-other-secret just changing the kubernetes pre x to knative pre x (ie
quarkus.kubernetes.readiness-probe.period-seconds to
quarkus.kubernetes.resources.requests.memory=64Mi quarkus.knative.readiness-probe.period-seconds ). Remember to execute eval $(minikube -p minikube docker-
quarkus.kubernetes.resources.requests.cpu=250m env) to build images directly inside Minkube cluster.
quarkus.kubernetes.resources.limits.memory=512Mi There are also speci c properties for Knative:
quarkus.kubernetes.resources.limits.cpu=1000m
OpenShift
quarkus.kubernetes.deployment-target=knative
quarkus.knative.revision-name=my-revision Instead of adding Kubernetes extension, set container image s2i
All possible values are explained at quarkus.knative.traffic.my-revision.percentage=80 and the target to openshift for working with OpenShift, an
https://quarkus.io/guides/kubernetes#con guration-options. extension grouping all of the is created:
Labels and Annotations
List of con guration options: ./mvnw quarkus:add-extension
The generated manifest use the Kubernetes recommended labels -Dextensions="openshift"
kubernetes
and annotations.
https://quarkus.io/guides/kubernetes#con guration-options
"labels" : {
openshift Kubernetes Con guration Extension
"app.kubernetes.io/part-of" : "todo-app",
"app.kubernetes.io/name" : "todo-rest", https://quarkus.io/guides/kubernetes#openshift
Integration between MicroPro le Con g spec and Con gMaps &
"app.kubernetes.io/version" : "1.0-rc.1" Secrets:
} Knative
https://quarkus.io/guides/kubernetes#knative ./mvnw quarkus:add-extensions
"annotations": {
-Dextensions="quarkus-kubernetes-config"
"app.quarkus.io/vcs-url" : "<some url>", Using Existing Resources
"app.quarkus.io/commit-id" : "<some git SHA>",
} You an provide your Kubernetes resources in form of yaml/json and
they will provide additional resources or be used as base for the quarkus.kubernetes-config.enabled=true
generation process: quarkus.kubernetes-config.config-maps=cmap1,cmap2
You can override the labels by using the next properties:
Resources are added in src/main/kubernetes directory with the
target name ( kubernetes.json , openshift.json , knative.json , or the
quarkus.kubernetes.part-of=todo-app yml equivalents) with one orm ore Kubernetes resources. Any
quarkus.kubernetes.name=todo-rest resource found will be added in the generated manifests. If one of
quarkus.kubernetes.version=1.0-rc.1 the provided resources has the same name as one of the generated
ones, then the generated resource will be created on top of the
provided resource respecting existing content
Client certi cate le.
@ConfigProperty(name = "some.prop1") @Dependent
String someProp1; public class KubernetesClientProducer {
client-cert-data

@ConfigProperty(name = "some.prop2") Client certi cate data. @Produces
String someProp2; public KubernetesClient kubernetesClient() {
client-key-data Config config = new ConfigBuilder()
Client key data. .withMasterUrl("https://mymaster.com")
.build();
If the con g
key is a Quarkus con guration le
return new DefaultKubernetesClient(config);
application.properties / application.yaml , the content is parsed and client-key-algorithm
}
each key of the con guration le is used as con g property. Client key algorithm.
}
List of Kubernetes Con g parameters. client-key-passphrase

quarkus.kubernetes-config as pre x is skipped in the next table. Client key passphrase.


And inject it on code:
enabled username
@Inject
The application will attempt to look up the con guration from the Username. KubernetesClient client;
API server. (default: false )

password
ServiceList myServices = client.services().list();
fail-on-missing-config Password.
The application will not start if any of the con gured con g Service myservice = client.services()
sources cannot be located. (default: true ) watch-reconnect-interval .inNamespace("default")
Watch reconnect interval. (default: PT1S ) .withName("myservice")
config-maps .get();
Con gMaps to look for in the namespace that the Kubernetes watch-reconnect-limit

Client has been con gured for. Supports CSV. CustomResourceDefinitionList crds = client
Maximum reconnect attempts. (default: -1 ) .customResourceDefinitions()
namespace
.list();
connection-timeout
Access to Con gMaps from a speci c namespace. Maximum amount of time to wait for a connection. (default: dummyCRD = new CustomResourceDefinitionBuilder()
PT10S ) ...
secrets.enabled
.build()
Whether or not con guration can be read from secrets. (default: request-timeout client.customResourceDefinitions()
false ) .create(dummyCRD);
Maximum amount of time to wait for a request. (default: PT10S )

Kubernetes Client rolling-timeout


Maximum amount of time to wait for a rollout. (default: PT15M ) Testing
Quarkus integrates with Fabric8 Kubernetes Client.
Quarkus provides a Kubernetes Mock test resource that starts a
http-proxy
./mvnw quarkus:add-extension
mock of Kubernetes API server and sets the proper environment
HTTP proxy used to access the Kubernetes. variables needed by Kubernetes Client.
-Dextensions="quarkus-kubernetes-client"

https-proxy Register next dependency: io.quarkus:quarkus-test-kubernetes-


HTTPS proxy used to access the Kubernetes. client:test .
List of Kubernetes client parameters.
proxy-username
quarkus.kubernetes-client as pre x is skipped in the next table.
Proxy username.
trust-certs
proxy-password
Trust self-signed certi cates. (default: false )
Proxy password.
master-url
no-proxy
URL of Kubernetes API server.
IP addresses or hosts to exclude from proxying
namesapce

Default namespace. Or programmatically:

ca-cert-file
CA certi cate data.

client-cert-file
@QuarkusTestResource(KubernetesMockServerTestResource.clas <dependency> public class GreetingFunction {
s) <groupId>io.quarkus</groupId>
@QuarkusTest <artifactId>quarkus-test-amazon-lambda</artifactId> @Inject
public class KubernetesClientTest { <scope>test</scope> GreetingService service;
</dependency>
@MockServer @io.quarkus.funqy.Funq
private KubernetesMockServer mockServer; public String greet(String name) {}

@Test @Test @io.quarkus.funqy.Funq("HelloCustomer")
public void test() { public void testLambda() { public String greet(Customer name) {}
final Pod pod1 = ... MyInput in = new MyInput();
mockServer in.setGreeting("Hello"); @Funq
.expect() in.setName("Stu"); public Greeting greet(Friend friend,
.get() MyOutput out = LambdaClient.invoke(MyOutput.class, in); @io.quarkus.funqy.Context AwsContext ctx) {}
.withPath("/api/v1/namespaces/test/pods") } }
.andReturn(200,
new PodListBuilder()
.withNewMetadata() To scaffold a AWS Lambda run: In case of Amazon Lambda, only one Funqy function can be
.withResourceVersion("1")
exported per Amazon Lambda deployment. If there is only one
.endMetadata()
mvn archetype:generate \ method annotated with @Funq then no prob, if not, you need to set
.withItems(pod1, pod2)
-DarchetypeGroupId=io.quarkus \ the function name with quarkus.funqy.export property.
.build())
-DarchetypeArtifactId=quarkus-amazon-lambda-archetype \
.always();
}
-DarchetypeVersion={version} Funqy HTTP
}
You can invoke on Funqy functions in a pure HTTP environment
with simple adding the Funqy HTTP extension.
Azure Functions
AWS Lambda <dependency>
Quarkus can make a microservice be deployable to the Azure
<groupId>io.quarkus</groupId>
Functions.
Quarkus integrates with Amazon Lambda. <artifactId>quarkus-funqy-http</artifactId>
To scaffold a deployable microservice to the Azure Functions run: </dependency>
./mvnw quarkus:add-extension
-Dextensions="io.quarkus:quarkus-amazon-lambda"
mvn archetype:generate \
-DarchetypeGroupId=io.quarkus \ Funqy Cloud Events
-DarchetypeArtifactId=quarkus-azure-functions-http-archet
And then implement ype \ Add the extension:
com.amazonaws.services.lambda.runtime.RequestHandler interface. -DarchetypeVersion={version}

<dependency>
public class TestLambda <groupId>io.quarkus</groupId>
implements RequestHandler<MyInput, MyOutput> {
Funqy <artifactId>quarkus-funqy-knative-events</artifactId>
@Override </dependency>
public MyInput handleRequest(MyOutput input,
Quarkus Funqy is part of Quarkus’s serverless strategy and aims to
Context context) {
provide a portable Java API to write functions deployable to various
}
FaaS environments like AWS Lambda, Azure Functions, Knative, and
} @Funq
Knative events.
public String defaultChain(String input) {}

The interface
com.amazonaws.services.lambda.runtime.RequestStreamHandler is also The Cloud Event type that triggers the function is defaultChain . It
supported. generates a response that triggers a new Cloud Event whose type is
defaultChain.output and the event source is defaultChain .
The interface com.amazon.ask.SkillStreamHandler is also supported.
It can be changed by using the next properties:
You can set the handler name by using quarkus.lambda.handler
property or by annotating the Lambda with the CDI @Named
quarkus.funqy.knative-events.mapping.defaultChain.trigger=c
annotation.
onfigChain.output
Test quarkus.funqy.knative-events.mapping.defaultChain.response-
type=annotated
You can write tests for Amazon lambdas: quarkus.funqy.knative-events.mapping.defaultChain.response-
source=configChain
The properties are of form: quarkus.funqy.knative-events.mapping. Apache Camel Possible Swagger UI options with quarkus.swagger-ui pre x:
{function name}. .
urls
Apache Camel Quarkus has its own site:
Also can be overriden with The urls that will be included as options. (ie
https://github.com/apache/camel-quarkus quarkus.swagger-
@io.quarkus.funqy.knative.events.CloudEventMapping annotation. ui.urls.petstore=https://petstore.swagger.io/v2/swagger.json )

@Funq
WebSockets
urls-primary-name
@CloudEventMapping(trigger = "annotated", responseSource = If urls option is used, this will be the name of the default
Quarkus can be used to handling web sockets.
"annotated", responseType = "lastChainLink") selection.
public String annotatedChain(String input) {}
./mvnw quarkus:add-extension
title
-Dextensions="io.quarkus:quarkus-undertow-websockets"
The html title for the page.
responseType chains annotatedChain response to lastChainLink
function. theme
And web sockets classes can be used:
Swagger UI theme to be used.
@Funq
public void lastChainLink(String input, @ServerEndpoint("/chat/{username}")
footer
@Context io.quarkus.funqy.knative.events.CloudE @ApplicationScoped
vent event) {} 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.
A K-Native Trigger looks like: @PathParam("username") String username) {}
display-operation-id
apiVersion: eventing.knative.dev/v1alpha1 @OnClose
kind: Trigger
Controls the display of operationId in operations list.
public void onClose(..) {}
metadata:
name: defaultchain default-models-expand-depth
@OnError
spec: public void onError(..., Throwable throwable) {} The default expansion depth for models.
filter:
attributes: @OnMessage default-model-expand-depth
type: defaultChain public void onMessage(...) {} The default expansion depth for the model on the model-example
subscriber: section.
ref: }
apiVersion: serving.knative.dev/v1
default-model-rendering
kind: Service
name: funqy-knative-events-quickstart 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
And to curl from inside the Kubernetes cluster:
using Swagger UI. "Try it out" requests.
curl -v "http://default-broker.knativetutorial.svc.cluster.
./mvnw quarkus:add-extension doc-expansion
local" \
-X POST \
-Dextensions="io.quarkus:quarkus-smallrye-openapi" Controls the default expansion setting for the operations and
-H "Ce-Id: 1234" \ tags.
-H "Ce-Specversion: 1.0" \
-H "Ce-Type: defaultChain" \ Then you only need to access to /openapi to get OpenAPI v3 spec filter
-H "Ce-Source: curl" \ of services. Enables ltering.
-H "Content-Type: application/json" \
-d '"Start"' 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 And then you can use them to send an email:
A list of presets to use in Swagger UI.
tag-sorter mailer.send(
Apply a sort to the tag list of each API. You can customize the output by using Open API v3 annotations. Mail.withText("[email protected]", "Subject", "Body")
);
on-complete @Schema(name="Developers",
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 { Reactive Mail client
@Schema(required = true, example = "Alex")
syntax-highlight private String name; @Inject
}
Set to false to deactivate syntax highlighting of payloads and ReactiveMailer reactiveMailer;

cURL command.
@POST CompletionStage<Response> stage =
@Path("/developer") reactiveMailer.send(
oauth2-redirect-url
@Operation(summary = "Create deeloper", Mail.withText("[email protected]", "Subject", "Body")
OAuth redirect URL. description = "Only be done by admin.") )
public Response createDeveloper( .subscribeAsCompletionStage()
request-interceptor @RequestBody(description = "Developer object", .thenApply(x -> Response.accepted().build());
Function to intercept remote de nition, "Try it out", and OAuth 2.0 required = true,
requests. content = @Content(schema =
@Schema(implementation = Developer.class)))
request-curl-options Developer developer) If you are using quarkus-resteasy-mutiny , you can return
io.smallrye.mutiny.Uni type.
Array of command line options available to the curl command.
Mail class contains methods to add cc , bcc , headers , bounce
response-interceptor All possible annotations can be seen at
address , reply to , attachments , inline attachments and html body .
Function to intercept remote de nition, "Try it out", and OAuth 2.0 org.eclipse.micropro le.openapi.annotations package.
responses.
You can also serve OpenAPI Schema from static les instead of mailer.send(Mail.withHtml("[email protected]", "Subject", body)
dynamically generated from annotation scanning. .addInlineAttachment("quarkus.png",
show-mutated-request
new File("quarkus.png"),
Uses the mutated request returned from a requestInterceptor to You need to put OpenAPIdocumentation under META-INF directory "image/png", "<[email protected]>"));
produce the curl command in the UI. (ie: META-INF/openapi.yaml ).

supported-submit-methods A request to /openapi will serve the combined OpenAPI document


from the static le and the generated from annotations. You can If you need deep control you can inject Vert.x mail client
List of HTTP methods that have the "Try it out" feature enabled.
disable the scanning documents by adding the next con guration @Inject MailClient client;
property: mp.openapi.scan.disable=true .
validator-url You need to con gure SMTP properties to be able to send an email:
Swagger UI attempts to validate specs against swagger.io’s Other valid document paths are: META-INF/openapi.yml , META-
online validator. INF/openapi.json , WEB-INF/classes/META-INF/openapi.yml , WEB- [email protected]
INF/classes/META-INF/openapi.yaml , WEB-INF/classes/META- quarkus.mailer.host=smtp.sendgrid.net
with-credentials INF/openapi.json . quarkus.mailer.port=465
Enables passing credentials, as de ned in the Fetch standard, in quarkus.mailer.ssl=true
CORS requests that are sent by the browser. You can store generated OpenAPI schema if quarkus.swagger- quarkus.mailer.username=....
ui.store-schema-directory is set. quarkus.mailer.password=....
model-property-macro

Function to set default values to each property in model.


Mail Sender
List of Mailer parameters. quarkus. as a pre x is skipped in the next
You can send emails by using Quarkus Mailer extension:
parameter-macro table.
Function to set default value to parameters.
./mvnw quarkus:add-extension Parameter Default Description
-Dextensions="io.quarkus:quarkus-mailer"
persist-authorization
mailer.from Default address.
It persists authorization data and it would not be lost on browser
close/refresh.
You can inject two possible classes io.quarkus.mailer.Mailer for
synchronous API or io.quarkus.mailer.reactive.ReactiveMailer for Emails not sent, just
false in prod , true in
layout
asynchronous/reactive API. mailer.mock printed and stored in
dev and test .
The name of a component available via the plugin system to use a MockMailbox .
as the top-level layout for Swagger UI.
@Inject
Mailer mailer; mailer.bounce-
plugins Default address.
address
A list of plugin functions to use in Swagger UI.
Parameter Default Description To start using it you only need to add the next extension:
@Inject
MockMailbox mailbox;
mailer.host mandatory SMTP host. ./mvnw quarkus:add-extension
@BeforeEach -Dextensions="kogito"
void init() {
mailer.port 25 SMTP port. mailbox.clear();
}

Apache Tika
mailer.username The username.
List<Mail> sent = mailbox
.getMessagesSentTo("[email protected]");
Quarkus integrates with Apache Tika to detect and extract
metadata/text from different le types:
mailer.password The password.
./mvnw quarkus:add-extension
Scheduled Tasks -Dextensions="quarkus-tika"
mailer.ssl false Enables SSL.
You can schedule periodic tasks with Quarkus.
mailer.trust-all false Trust all certi cates.
@ApplicationScoped @Inject
public class CounterBean { io.quarkus.tika.TikaParser parser;

Max open
mailer.max-pool-size 10 @POST
connections . @Scheduled(every="10s", delayed="1s")
void increment() {} @Path("/text")
@Consumes({ "text/plain", "application/pdf",
Hostname for @Scheduled(cron="0 15 10 * * ?") "application/vnd.oasis.opendocument.text" })
mailer.own-host-name HELO/EHLO and void morningTask() {} @Produces(MediaType.TEXT_PLAIN)
Message-ID } public String extractText(InputStream stream) {
return parser.parse(stream).getText();
}
Connection pool
mailer.keep-alive true every and cron
parameters can be surrounded with {} and the
enabled.
value is used as con g property to get the value.
You can con gure Apache Tika in application.properties le by
@Scheduled(cron = "{morning.check.cron.expr}") using next properties pre xed with quarkus :
mailer.disable-esmtp false Disable ESMTP.
void morningTask() {}
Parameter Default Description
TLS security mode.
And con gure the property into application.properties : Path to the Tika
mailer.start-tls OPTIONAL DISABLED , OPTIONAL , tika.tika-config-
tika-config.xml con guration
REQUIRED . path
resource.
morning.check.cron.expr=0 15 10 * * ?

Login mode. NONE ,


mailer.login NONE CSV of the
OPTIONAL , REQUIRED .
By default Quarkus expresion is used, but you can change that by abbreviated or full
setting quarkus.scheduler.cron-type property. quarkus.tika.parsers parser class to be
loaded by the
mailer.auth-methods All methods. Space-separated list.
quarkus.scheduler.cron-type=unix extension.

mailer.key-store Path of the key store.


The document may
org.quartz.Scheduler
can be injected as any other bean and tika.append-embedded- have other embedded
true
scehdule jobs programmatically. content documents. Set if
mailer.key-store-
Key store password. autmatically append.
password
@Inject
org.quartz.Scheduler quartz;
if you enable SSL for the mailer and you want to build a
native executable, you will need to enable the SSL support
JGit
quartz.scheduleJob(job, trigger);
quarkus.ssl.native=true .
Quarkus integrates with JGit to integrate with Git repositories:
Testing

If quarkus.mailer.mock is set to true , which is the default value in


Kogito ./mvnw quarkus:add-extension
-Dextensions="quarkus-jgit"
dev and test mode, you can inject MockMailbox to get the sent
Quarkus integrates with Kogito, a next-generation business
messages.
automation toolkit from Drools and jBPM projects for adding
business automation capabilities. And then you can start using JGit:
try (Git git = Git.cloneRepository() import org.jboss.stm.annotations.ReadLock; @ApplicationScoped
.setDirectory(tmpDir) import org.jboss.stm.annotations.State; public class TaskBean {
.setURI(url) import org.jboss.stm.annotations.WriteLock;
.call()) { @Transactional
return tmpDir.toString(); public class FlightServiceImpl @Scheduled(every = "10s")
} implements FlightService { void schedule() {
@State Task task = new Task();
private int numberOfBookings; task.persist();
}
When running in native mode, make sure to con gure SSL @ReadLock }
access correctly quarkus.ssl.native=true (Native and SSL). public int getNumberOfBookings() {
return numberOfBookings;
Web Resources }
To con gure in clustered mode vida DataSource:

You can serve web resources with Quarkus. You need to place web @WriteLock
quarkus.datasource.url=jdbc:postgresql://localhost/quarkus_
resources at src/main/resources/META-INF/resources and then they public void makeBooking(String details) {
test
are accessible (ie http://localhost:8080/index.html) numberOfBookings += 1;
} quarkus.datasource.driver=org.postgresql.Driver
# ...
By default static resources as served under the root context. You }

can change this by using quarkus.http.root-path property.
quarkus.quartz.clustered=true
quarkus.quartz.store-type=db
Transactional Memory Any member is saved/restored automatically ( @State is not
mandatory). You can use @NotState to avoid behaviour.
Quarkus integrates with the Software Transactional Memory (STM)
implementation provided by the Narayana project. Transaction boundaries You need to de ne the datasource used by clustered mode
and also import the database tables following the Quartz
Declarative schema.
./mvnw quarkus:add-extension
-Dextensions="narayana-stm"
@NestedTopLevel : De nes that the container will create a new Quartz can be con gured usinf the following properties with
top-level transaction for each method invocation. quarkus.quartz pre x:

Transactional objects must be interfaces and annotated with @Nested : De nes that the container will create a new top-level clustered
org.jboss.stm.annotations.Transactional . or nested transaction for each method invocation.
Enable cluster mode or not.
Programmatically
@Transactional store-type
@NestedTopLevel
AtomicAction aa = new AtomicAction(); The type of store to use. Possible values: ram , db (default: ram )
public interface FlightService {

int getNumberOfBookings();
aa.begin(); datasource
void makeBooking(String details);
}
{ The name of the datasource to use.
try {
flightService.makeBooking("BA123 ..."); table-prefix
taxiService.makeBooking("East Coast Taxis ...");
The pessimistic strategy is the default one, you can change to The pre x for quartz job store tables. (default: QRTZ_ )

optimistic by using @Optimistic . aa.commit();
trigger-listeners.<name>.class
} catch (Exception e) {
Then you need to create the object inside org.jboss.stm.Container . aa.abort(); Class name for the trigger.
}
Container<FlightService> container = new Container<>(); } trigger-listeners.<name>.property-name
FlightServiceImpl instance = new FlightServiceImpl(); The properties passed to the class.
FlightService flightServiceProxy = container.create(instanc
e);
Quartz job-listeners.<name>.class

Class name for the job.


Quarkus integrates with Quartz to schedule periodic clustered
The implementation of the service sets the locking and what needs job-listeners.<name>.property-name
tasks.
to be saved/restored:
The properties passed to the class.
./mvnw quarkus:add-extension
-Dextensions="quartz" plugins.<name>.class

Class name for the plugin.

plugins.<name>.property-name

The properties passed to the class


instance-name To render the template:
{#for i in total}
The name of the Quartz instance. (default: {i}:
QuarkusQuartzScheduler ) public class Item { {/for}
public String name;
thread-count public BigDecimal price;
The size of scheduler thread pool. (default: 25 ) }
The next map methods are supported:

@Inject
thread-priority
io.quarkus.qute.Template item; {#for key in map.keySet}
Thread priority of worker threads in the pool. (default: 5 ) {#for value in map.values}
@GET {map.size}
force-start @Path("{id}") {#if map.isEmpty}
The scheduler will be started even if no scheduled business @Produces(MediaType.TEXT_HTML) {map['foo']
methods are found. public TemplateInstance get(@PathParam("id") Integer id) {
return item.data("item", service.findItem(id));

Qute } The next list methods are supported:



@TemplateExtension
Qute is a templating engine designed speci cally to meet the {list[0]}
static BigDecimal discountedPrice(Item item) {
Quarkus needs. Templates should be placed by default at
return item.price.multiply(new BigDecimal("0.9"));
src/main/resources/templates aand subdirectories.
}
The next number methods are supported:
./mvnw quarkus:add-extension @TemplateExtension(namespace = "str")
-Dextensions="quarkus-resteasy-qute" public static class StringExtensions { {#if counter.mod(5) == 0}
static String reverse(String val) {
return new StringBuilder(val).reverse().toString();
Templates can be de ned in any format, in case of HTML: }
}
Message Bundling
item.html

@io.quarkus.qute.i18n.MessageBundle
{@org.acme.Item item}
public interface AppMessages {
<!DOCTYPE html> If @ResourcePath is not used in Template then the name of the eld is
@io.quarkus.qute.i18n.Message("Hello {name}!")
<html> used as le name. In this case the le should be
String hello_name(String name);
<head> src/main/resources/templates/item.{} . Extension of the le is not
}
<meta charset="UTF-8"> required to be set.
<title>{item.name}</title>
</head> discountedPrice is not a eld of the POJO but a method call.
<body> Method de nition must be annotated with @TemplateExtension and There are 3 methods to inject the message:
<h1>{item.name ?: 'Unknown'}</h1> be static method. First parameter is used to match the base object
<h2>{str:reverse('Hello')}</h2> ( Item ). @TemplateExtension can be used at class level: MessageBundles.get(AppMessages.class).hello_name("Lucie");
<div>Price: {item.price}</div>
{#if item.price > 100} @TemplateExtension
<div>Discounted Price: {item.discountedPrice}</div> public class MyExtensions {
or
{/if} static BigDecimal discountedPrice(Item item) {
</body> return item.price.multiply(new BigDecimal("0.9"));
</html> } @Inject AppMessages app;
}
app.hello_name("Lucie");

First line is not mandatory but helps on doing property checks at


compilation time. Methods with multiple parameters are supported too:
or
Including templates passing parameters:
{item.discountedPrice(2)}
<p>{msg:hello_name('Lucie')}</p>
<html>
<head>
<meta charset="UTF-8"> static BigDecimal discountedPrice(Item item, int scale) {
Localization
<title>Simple Include</title> return item.price.multiply(scale);
</head> } There are two ways to set localized message:
<body>
{#include foo limit=10 /}
</body>
Qute for syntax supports any instance of Iterable , Map.EntrySet ,
</html>
Stream or Integer .
And the con guration to send all errors occuring in the package
@io.quarkus.qute.i18n.Localized("de") @ApplicationScoped
org.example to Sentrty with DSN https://[email protected]/1234 :
public interface GermanAppMessages { public class CachedBean {

@Override quarkus.log.sentry=true @CacheResult(cacheName = "foo")
@io.quarkus.qute.i18n.Message("Hallo {name}!") quarkus.log.sentry.dsn=https://[email protected]/1234 public Object load(Object key) {}
String hello_name(String name); quarkus.log.sentry.level=ERROR
} quarkus.log.sentry.in-app-packages=org.example @CacheInvalidate(cacheName = "foo")
public void invalidate(Object key) {}

Full list of con guration properties having quarkus.log as pre x: @CacheInvalidateAll(cacheName = "foo")
or
public void invalidateAll() {}
msg_de.properties sentry.enable }

hello_name=Hallo {name}! Enable the Sentry logging extension (default: false)

sentry.dsn You can disable the caching system by setting


Where to send events. quarkus.cache.enabled property to false .
You can render programmaticaly the templates too:
This extension uses Caffeine as its underlying caching provider.
sentry.level
// file located at src/main/resources/templates/reports/v1/
report_01.{}
Log level (default: WARN ) Each cache can be con gured individually:
@ResourcePath("reports/v1/report_01")
Template report; sentry.in-app-packages quarkus.cache.caffeine."foo".initial-capacity=10
Con gure which package pre xes your application uses. quarkus.cache.caffeine."foo".maximum-size=20
String output = report quarkus.cache.caffeine."foo".expire-after-write
.data("samples", service.get()) JSch quarkus.cache.caffeine."bar".maximum-size=1000
.render();

Quarkus integrates with Jsch for SSH communication.


Full list of con guration properties having quarkus.cache.caffeine.
Reactive and Async [cache-name] as pre x:
./mvnw quarkus:add-extension
-Dextensions="quarkus-jsch"
initial-capacity
CompletionStage<String> async = report.renderAsync();
Multi<String> publisher = report.createMulti(); Minimum total size for the internal data structures.

Uni<String> content = io.smallrye.mutiny.Uni.createFrom() JSch jsch = new JSch(); maximum-size
.completionStage(() -> report.r Session session = jsch.getSession(null, host, port); Maximum number of entries the cache may contain.
enderAsync()); session.setConfig("StrictHostKeyChecking", "no");
session.connect();
expire-after-write

Speci es that each entry should be automatically removed from


Qute Mail Integration the cache once a xed duration has elapsed after the entry’s
Cache creation, or last write.
@Inject
MailTemplate hello; Quarkus can cache method calls by using as key the tuple (method expire-after-access
+ arguments). Speci es that each entry should be automatically removed from
CompletionStage<Void> c = hello.to("[email protected]") the cache once a xed duration has elapsed after the entry’s
.subject("Hello from Qute template") ./mvnw quarkus:add-extension creation, or last write.
.data("name", "John") -Dextensions="cache"
.send();
You can multiple cache annotations on a single method.

@io.quarkus.cache.CacheResult(cacheName = "weather-cache") If you see a javax.enterprise.context.ContextNotActiveException ,


INFO: Template located at src/main/resources/templates/hello.
public String getDailyForecast(LocalDate date, String city) you need to add the quarkus-smallrye-context-propagation
[html|txt] .
{} extension.
Sentry
Banner
Quarkus integrates with Sentry for logging errors into an error @CacheInvalidate removes the element represented by the
monitoring system. calculated cache key from cache. @CacheInvalidateAll removes all Banner is printed by default. It is not an extension but placed in the
entries from the cache. @CacheKey to speci cally set the arguments core.
to be used as key instead of all.
./mvnw quarkus:add-extension
quarkus.banner.path
-Dextensions="quarkus-logging-sentry"
Path is relative to root of the classpath. (default:
)
quarkus.banner.enabled Keys whose value is a raw string. The keys that end up in the user
./mvnw quarkus:add-extension
Enables banner. (default : true ) con guration are the keys speci ed her with '/' replaced by '.'
-Dextensions="quarkus-smallrye-context-propagation"

OptaPlanner properties-value-keys
Keys whose value represents a properties-like le conttent.
If using mutiny extension together you already get context
Quarkus integrates with OptaPlanner. propagation for ArC, RESTEasy and transactions. With
fail-on-missing-key
CompletionStage you need to:
./mvnw quarkus:add-extension If the application will not start if any of the con gured con g
-Dextensions="quarkus-optaplanner, quarkus-optaplanner-ja sources cannot be located. (default: true )
@Inject ThreadContext threadContext;
ckson" @Inject ManagedExecutor managedExecutor;
trust-store

threadContext.withContextCapture(..) TrustStore to be used containing the SSL certi cate used by
.thenApplyAsync(r -> {}, managedExecutor); Consul agent.
@PlanningSolution
public class TimeTable { trust-store-password
}
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.
@Inject
private SolverManager<TimeTable, UUID> solverManager; throughout the reactive callback.
key-password

UUID problemId = UUID.randomUUID(); Con guration from HasiCorp Consul Password to recover key from KeyStore for SSL client
SolverJob<TimeTable, UUID> solverJob = solverManager.solve authentication with Consul agent.
(problemId, problem); You can read runtime con guration from HashiCorp Consul.
TimeTable solution = solverJob.getFinalBestSolution(); agent.host-port

./mvnw quarkus:add-extension Consul agent host. (default: localhost:8500 )


-Dextensions="consul-config"
Possible con guration options pre xed with quarkus.optaplanner : agent.use-https

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


solver-config-xml
You need to con gure Consul:
A classpath resource to read the solver con guration XML. Not agent.token
mandatory. quarkus.consul-config.enabled=true Consul token to be provided when authentication is enabled.
quarkus.consul-config.agent.host-port=localhost:8500
solver.environment-mode
quarkus.consul-config.properties-value-keys=config/consul-t agent.key-store
Enable runtime assertions to detect common bugs in your est KeyStore (classpath or lesystem) to be used containing the SSL
implementation during development. Possible values: certi cate used by Consul agent.
FAST_ASSERT , FULL_ASSERT , NON_INTRUSIVE_FULL_ASSERT ,
NON_REPRODUCIBLE , REPRODUCIBLE . (default: REPRODUCIBLE )
agent.key-store-password
@ConfigProperty(name = "greeting.message")
solver.move-thread-count String message; Password of KeyStore.
Enable multithreaded solving for a single problem. Possible
agent.trust-certs
values: MOVE_THREAD_COUNT_NONE , MOVE_THREAD_COUNT_AUTO , a number
or formula based on the available processors. (default: In Consul: To trust all certi cates or not.
MOVE_THREAD_COUNT_NONE )
agent.connection-timeout
"Key": "config/consul-test",
solver.termination.spent-limit "Value": "greeting.message=Hello from Consul" Connection timeout. (default: 10S )
How long the solver can run. (ie 5s )
agent.read-timeout

solver.termination.unimproved-spent-limit Possible con guration parameters, pre xed with quarkus.consul- Reading timeout. (default: 60S )
How long the solver can run without nding a new best solution config :
after nding a new best solution. (ie 2h ) Amazon Alexa
enabled
solver.termination.best-score-limit The application will attempt to look up the con guration from You can use Amazon Alexa by adding the extension:
Terminates the solver when a speci c or higher score has been Consul. (default: false )
reached. (ie 0hard/-1000soft ) ./mvnw quarkus:add-extension
prefix -Dextensions="quarkus-amazon-alexa"
solver-manager.parallel-solver-count Common pre x that all keys share when looking up the keys from
The number of solvers that run in parallel. (default: Consul. The pre x is not included in the keys of the user
PARALLEL_SOLVER_COUNT_AUTO ) con guration
WebJar Locator
raw-value-keys
Context Propagation
To change how you can refer to webjars skipping the version part
<dependency> Spring DI
you can use WebJars locator extension. <groupId>software.amazon.awssdk</groupId>
<artifactId>netty-nio-client</artifactId> Quarkus provides a compatibility layer for Spring dependency
./mvnw quarkus:add-extension </dependency> injection.
-Dextensions="webjars-locator"

./mvnw quarkus:add-extension
Con guration properties are the same as Amazon DynamoDB but -Dextensions="quarkus-spring-di"
Then the JavaScript location is changed from changing the pre x from dynamodb to ses .
/webjars/jquery/3.1.1/jquery.min.js to
/webjars/jquery/jquery.min.js in your HTML les. Jbang Some examples of what you can do. Notice that annotations are
the Spring original ones.
Amazon SES Creating an initial script:
@Configuration
public class AppConfiguration {
mvn quarkus:add-extension jbang scripting/quarkusapp.java

-Dextensions="amazon-ses"
@Bean(name = "capitalizeFunction")
public StringFunction capitalizer() {
Adding Quarkus dependencies in script: return String::toUpperCase;
@Inject }
software.amazon.awssdk.services.ses.SesClient sesClient; //DEPS io.quarkus:quarkus-resteasy:{quarkus-version} }

@Inject
software.amazon.awssdk.services.ses.SesAsyncClient sesClien Put some Quarkus CLI code: Or as a component:
t;
@Component("noopFunction")
@Path("/hello")
public class NoOpSingleStringFunction
@ApplicationScoped
implements StringFunction {
quarkus.ses.endpoint-override=http://localhost:8012 public class quarkusapp {
}
quarkus.ses.aws.region=us-east-1 @GET
quarkus.ses.aws.credentials.type=static public String sayHello() {
quarkus.ses.aws.credentials.static-provider.access-key-id=t return "hello";
est-key } Also as a service and injection properties from
quarkus.ses.aws.credentials.static-provider.secret-access-k public static void main(String[] args) { application.properties .
ey=test-secret Quarkus.run(args);
} @Service
} public class MessageProducer {

You need to set a HTTP client either URL Connection :
@Value("${greeting.message}")
To run the script: String message;
<dependency>
<groupId>software.amazon.awssdk</groupId> }
<artifactId>url-connection-client</artifactId> jbang quarkusapp.java
</dependency>

And you can inject using Autowired or constructor in a component


and in a JAX-RS resource too.
or Apache HTTP:
@Component
<dependency> public class GreeterBean {
<groupId>software.amazon.awssdk</groupId>
<artifactId>apache-client</artifactId> private final MessageProducer messageProducer;
</dependency>
@Autowired @Qualifier("noopFunction")
StringFunction noopStringFunction;

quarkus.ses.sync-client.type=apache
public GreeterBean(MessageProducer messageProducer) {
this.messageProducer = messageProducer;
}
Or async: }
Spring Boot Con guration enabled dependency).
Enables read con guration from Spring Cloud Con g Server.
Quarkus provides a compatibility layer for Spring Boot (default: false ) Spring Data JPA
ConfigurationProperties .
fail-fast While users are encouraged to use Hibernate ORM with Panache
./mvnw quarkus:add-extension True to not start application if cannot access to the server. for Relational Database access, Quarkus provides a compatibility
-Dextensions="quarkus-spring-boot-properties" (default: false ) layer for Spring Data JPA repositories.

connection-timeout ./mvnw quarkus:add-extension


-Dextensions="quarkus-spring-data-jpa"
The amount of time to wait when initially establishing a
@ConfigurationProperties("example")
connection before giving up and timing out. (default: 10S )
public final class ClassProperties {

read-timeout INFO: Of course you still need to add the JDBC driver, and con gure
private String value;
The amount of time to wait for a read on a socket before an it in application.properties .
private AnotherClass anotherClass;
exception is thrown. (default: 60S )
// getters/setters public interface FruitRepository
} Spring Web extends CrudRepository<Fruit, Long> {
List<Fruit> findByColor(String color);
}
Quarkus provides a compatibility layer for Spring Web.
example.value=class-value
example.anotherClass.value=true ./mvnw quarkus:add-extension
-Dextensions="quarkus-spring-web" And then you can inject it either as shown in Spring DI or in Spring
Web.

Interfaces supported:
Spring Cloud Con g Client Speci cally supports the REST related features. Notice that
infrastructure things like BeanPostProcessor will not be executed. org.springframework.data.repository.Repository
Quarkus integrates Spring Cloud Con g Client and MicroPro le
Con g spec. org.springframework.data.repository.CrudRepository
@RestController
@RequestMapping("/greeting")
./mvnw quarkus:add-extension org.springframework.data.repository.PagingAndSortingReposito
public class GreetingController {
-Dextensions="quarkus-spring-cloud-config-client" ry

private final GreetingBean greetingBean; org.springframework.data.jpa.repository.JpaRepository .

You need to con gure the extension: public GreetingController(GreetingBean greetingBean) { INFO: Generated repositories are automatically annotated with
this.greetingBean = greetingBean; @Transactional .
}
quarkus.spring-cloud-config.uri=http://localhost:8089
Repository fragments is also supported:
quarkus.spring-cloud-config.username=user
@GetMapping("/{name}")
quarkus.spring-cloud-config.password=pass
public Greeting hello(@PathVariable(name = "name") public interface PersonRepository
quarkus.spring-cloud-config.enabled=true
String name) { extends JpaRepository<Person, Long>, PersonFragment {
return new Greeting(greetingBean.greet(name));
} void makeNameUpperCase(Person person);
@ConfigProperty(name = "greeting.message") } }
String greeting;

Supported annotations are: RestController , RequestMapping , User de ned queries:


Pre x is quarkus.spring-cloud-config . GetMapping , PostMapping , PutMapping , DeleteMapping , PatchMapping ,
RequestParam , RequestHeader , MatrixVariable , PathVariable ,
uri CookieValue , RequestBody , ResponseStatus , ExceptionHandler and
RestControllerAdvice .
Base URI where the Spring Cloud Con g Server is available.
(default: localhost:8888 )
If you scaffold the project with spring-web extension, then
username
Spring Web annotations are sed in the generated project.
mvn io.quarkus:quarkus-maven-plugin:1.10.2.Final:create …
-
Username to be used if the Con g Server has BASIC Auth Dextensions="spring-web" .
enabled.
The next return types are supported:
password org.springframework.http.ResponseEntity and java.util.Map .
Password to be used if the Con g Server has BASIC Auth
enabled. The next parameter types are supported: An Exception argument
d / ( ddi
@PreAuthorize("hasRole(@roles.USER)") where roles is a bean
@Query("select m from Movie m where m.rating = ?1") @org.springframework.cache.annotation.Cacheable("someCache"
de ned with @Component annotation and USER is a public eld
Iterator<Movie> findByRating(String rating); )
of the class.
public Greeting greet(String name) {}
@Modifying
hasAnyRole
@Query("delete from Movie where rating = :rating")
void deleteByRating(@Param("rating") String rating); @PreAuthorize("hasAnyRole(@roles.USER, 'view')") Quarkus provides compatibility with the following Spring Cache

annotations:
@Query(value = "SELECT COUNT(*), publicationYear FROM Book Permit and Deny All
GROUP BY publicationYear") @Cacheable
List<BookCountByYear> findAllByPublicationYear2(); @PreAuthorize("permitAll()")
@CachePut
interface BookCountByYear { @PreAuthorize("denyAll()")
int getPublicationYear(); @CacheEvict
Anonymous and Authenticated
Long getCount();
@PreAuthorize("isAnonymous()")
Spring Schedule
}

@PreAuthorize("isAuthenticated()") Quarkus provides a compatibility layer for Spring Scheduled


annotation.
What is currently unsupported: Expressions
./mvnw quarkus:add-extension
Methods of Checks if the current logged in user is the same as the -Dextensions="spring-scheduled"
org.springframework.data.repository.query.QueryByExampleExec username method parameter:
utor
@PreAuthorize("#person.name == authentication.principal.use
QueryDSL support rname") @org.springframework.scheduling.annotation.Scheduled(cron=
public void doSomethingElse(Person person){} "*/5 * * * * ?")
Customizing the base repository void cronJob() {
System.out.println("Cron expression hardcoded");
java.util.concurrent.Future as return type
}
Checks if calling a method if user can access:
Native and named queries when using @Query
@Scheduled(fixedRate = 1000)
@PreAuthorize("@personChecker.check(#person, authenticatio
Spring Security n.principal.username)")
@Scheduled(cron = "{cron.expr}")

public void doSomething(Person person){}


Quarkus provides a compatibility layer for Spring Security.
@Component
./mvnw quarkus:add-extension public class PersonChecker {
-Dextensions="spring-security" public boolean check(Person person, String username) {
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
methods: @PreAuthorize("hasAnyRole('user', 'admin') AND #user == pri
ncipal.username")
@Secured("admin") public void allowedForUser(String user) {}
@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
Some examples: -Dextensions="spring-cache"

hasRole

@PreAuthorize("hasRole('admin')")
Resources Authors : 1.10.2.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