Sei sulla pagina 1di 35

Quarkus

Cheat-Sheet

What is Quarkus? Or in Kotlin: @ConfigProperty(name = "greetings.message")


String message;
Quarkus is a Kubernetes Native Java stack tailored for GraalVM & plugins {
OpenJDK HotSpot, crafted from the best of breed Java libraries and java @ConfigProperty(name = "greetings.message",
standards. Also focused on developer experience, making things } defaultValue = "Hello")
just work with little to no con guration and allowing to do live apply(plugin = "io.quarkus") String messageWithDefault;
coding.
repositories { @ConfigProperty(name = "greetings.message")
Cheat-sheet tested with Quarkus 1.1.0.Final. mavenCentral() Optional<String> optionalMessage;
}
Getting Started
dependencies {
Properties can be set as:
Quarkus comes with a Maven archetype to scaffold a very simple implementation(enforcedPlatform("io.quarkus:quarkus-bo
starting project. m:0.26.1"))
Environment variables ( GREETINGS_MESSAGE ).
implementation("io.quarkus:quarkus-resteasy")
} System properties ( -Dgreetings.message ).
mvn io.quarkus:quarkus-maven-plugin:1.1.0.Final:create \
-DprojectGroupId=org.acme \
-DprojectArtifactId=getting-started \
Resources src/main/resources/application.properties .
-DclassName="org.acme.quickstart.GreetingResource" \ Extensions External con g directory under the current working directory:
-Dpath="/hello"
config/application.properties .
Quarkus comes with extensions to integrate with some libraries
such as JSON-B, Camel or MicroPro le spec. To list all available
greetings.message = Hello World
This creates a simple JAX-RS resource called GreetingResource . extensions just run:

@Path("/hello") ./mvnw quarkus:list-extensions


Array , List and Set are supported. The delimiter is comma
public class GreetingResource {

( , ) char and \ is the escape char.
@GET
You can use -DsearchPattern=panache to lter out all Con guration Pro les
@Produces(MediaType.TEXT_PLAIN)
extensions except the ones matching the expression.
public String hello() {
Quarkus allow you to have multiple con guration in the same le
return "hello";
And to register the extensions into build tool: ( application.properties ).
}
} The syntax for this is %{profile}.config.key=value .
./mvnw quarkus:add-extension -Dextensions=""

quarkus.http.port=9090
Gradle extensions property supports CSV format to register more
%dev.quarkus.http.port=8181

than one extension at once.


There is no way to scaffold a project in Gradle but you only need to
do: HTTP port will be 9090, unless the 'dev' pro le is active.
Application Lifecycle
plugins { Default pro les are:
id 'java'
You can be noti ed when the application starts/stops by observing
StartupEvent and ShutdownEvent events. dev : Activated when in development mode ( quarkus:dev ).
id 'io.quarkus' version '0.26.1'
}
test : Activated when running tests.
@ApplicationScoped
repositories { public class ApplicationLifecycle {
prod : The default pro le when not running in development or
mavenCentral() void onStart(@Observes StartupEvent event) {}
test mode
} void onStop(@Observes ShutdownEvent event) {}
} You can create custom pro le names by enabling the pro le either
dependencies { setting quarkus.profile system property or QUARKUS_PROFILE
implementation enforcedPlatform('io.quarkus:quarkus-bo environment variable.
m:0.26.1')
implementation 'io.quarkus:quarkus-resteasy'
Adding Con guration Parameters
quarkus.http.port=9090
}
To add con guration to your application, Quarkus relies on %staging.quarkus.http.port=9999
MicroPro le Con g spec.
And enable it quarkus.profile=staging .
@ConfigProperties(prefix = "greeting") quarkus:
public class GreetingConfiguration { http:
You can also set it in the build tool:
public String message; cors:
public HiddenConfig hidden; ~: true
<groupId>org.apache.maven.plugins</groupId> methods: GET,PUT,POST
<artifactId>maven-surefire-plugin</artifactId> public static class HiddenConfig {
<version>${surefire-plugin.version}</version> public List<String> recipients;
<configuration> }
<systemPropertyVariables> Is equivalent to:
}
<quarkus.test.profile>foo</quarkus.test.profile>
<buildDirectory>${project.build.directory} quarkus.http.cors=true
</buildDirectory> quarkus.http.cors.methods=GET,PUT,POST
</systemPropertyVariables> And an application.properties mapping previous class:
</configuration>
greeting.message = hello
Custom Loader
greeting.hidden.recipients=Jane,John
You can implement your own ConfigSource to load con guration
Same for maven-failsafe-plugin . from different places than the default ones provided by Quarkus.
Bean Validation is also supported so properties are validated at For example, database, custom XML, REST Endpoints, …
test { startup time, for example @Size(min = 20) public String message; .
You need to create a new class and implement ConfigSource
useJUnitPlatform()
prefix attribute is not mandatory. If not provided, attribute interface:
systemProperty "quarkus.test.profile", "foo"
} is determined by class name (ie GreeetingConfiguration is
translated to greeting or GreetingExtraConfiguration to package com.acme.config;
greeting-extra ). The su x of the class is always removed. public class InMemoryConfig implements ConfigSource {

@Con gProperties YAML Con g private Map<String, String> prop = new HashMap<>();

As an alternative to injecting multiple related con guration values, YAML con guration is also supported. The con guration le is public InMemoryConfig() {
you can also use the @io.quarkus.arc.config.ConfigProperties called application.yaml and you need to register a dependency to // Init properties
annotation to group properties. enable its support: }

pom.xml
@ConfigProperties(prefix = "greeting") @Override
public class GreetingConfiguration { <dependency> public int getOrdinal() {
private String message; <groupId>io.quarkus</groupId> // The highest ordinal takes precedence
// getter/setter <artifactId>quarkus-config-yaml</artifactId> return 900;
} </dependency> }

@Override
This class maps greeting.message property de ned in public Map<String, String> getProperties() {
application.properties . quarkus: return prop;
datasource: }
You can inject this class by using CDI @Inject GreetingConfiguration url: jdbc:postgresql://localhost:5432/some-database
greeting; . driver: org.postgresql.Driver @Override
public String getValue(String propertyName) {
Also you can use an interface approach: return prop.get(propertyName);
}
Or with pro les:
@ConfigProperties(prefix = "greeting")
public interface GreetingConfiguration { @Override
"%dev": public String getName() {

quarkus: return "MemoryConfigSource";
@ConfigProperty(name = "message")
datasource: }
String message();
url: jdbc:postgresql://localhost:5432/some-database }
String getSuffix();
driver: org.postgresql.Driver

If property does not follow getter/setter naming convention you Then you need to register the ConfigSource as Java service. Create
In case of subkeys ~ is used to refer to the unpre xed part. a le with the following content:
need to use org.eclipse.microprofile.config.inject.ConfigProperty
to set it. /META-INF/services/org.eclipse.microprofile.config.spi.ConfigSource

Nested objects are also supporte: com.acme.config.InMemoryConfig


Custom Converters Produces Any POJO is marshaled/unmarshalled automatically.

You can implement your own conversion types from String. You can also create a factory of an object by using
public class Sauce {
Implement org.eclipse.microprofile.config.spi.Converter @javax.enterprise.inject.Produces annotation.
private String name;
interface:
private long scovilleHeatUnits;
@Produces
@Priority(DEFAULT_QUARKUS_CONVERTER_PRIORITY + 100) @ApplicationScoped // getter/setters
public class CustomInstantConverter Message message() { }
implements Converter<Instant> { Message m = new Message();
m.setMsn("Hello");
@Override return m;
public Instant convert(String value) { }
JSON equivalent:
if ("now".equals(value.trim())) {
return Instant.now(); @Inject {
} Message msg; "name":"Blair's Ultra Death",
return Instant.parse(value); "scovilleHeatUnits": 1100000
} }
}
Quali ers

You can use quali ers to return different implementations of the In a POST endpoint example:
@Priority annotation is used to override the default same interface or to customize the con guration of the bean.
InstantConverter . @POST
@Qualifier @Consumes(MediaType.APPLICATION_JSON)
Then you need to register the Converter as Java service. Create a @Retention(RUNTIME) public Response create(Sauce sauce) {
le with the following content: @Target({TYPE, METHOD, FIELD, PARAMETER}) // Create Sauce
/META-INF/services/org.eclipse.microprofile.config.spi.Converter public @interface Quote { return Response.created(URI.create(sauce.getId()))
@Nonbinding String value(); .build();
com.acme.config.CustomInstantConverter } }

@Produces
@Quote("")
Custom Context Path To work with Jackson you need to add:
Message message(InjectionPoint msg) {
Message m = new Message();
By default Undertow will serve content from under the root context. m.setMsn( ./mvnw quarkus:add-extension
If you want to change this you can use the quarkus.servlet.context- msg.getAnnotated() -Dextensions="quarkus-resteasy-jackson"
path con g key to set the context path. .getAnnotation(Quote.class)
.value()
Injection ); If you don’t want to use the default ObjectMapper you can customize
it by:
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 }
@ApplicationScoped
implemented.
public class CustomObjectMapperConfig {
@Inject
@Singleton
@Quote("Aloha Beach")
@ApplicationScoped @Produces
Message message;
public class GreetingService { public ObjectMapper objectMapper() {
ObjectMapper objectMapper = new ObjectMapper();
public String message(String message) { // perform configuration
return message.toUpperCase(); Quarkus breaks the CDI spec by allowing you to inject return objectMapper;
} quali ed beans without using @Inject annotation. }
} }

@Quote("Aloha Beach")
Message message;
Scope annotation is mandatory to make the bean discoverable. XML Marshalling/Unmarshalling
@Inject
JSON Marshalling/Unmarshalling To work with JAX-B you need to add a dependency:
GreetingService greetingService;

To work with JSON-B you need to add a dependency: ./mvnw quarkus:add-extension


-Dextensions="quarkus-resteasy-jaxb"
Quarkus is designed with Substrate VM in mind. For this ./mvnw quarkus:add-extension
reason, we encourage you to use package-private scope -Dextensions="io.quarkus:quarkus-resteasy-jsonb"
instead of private. Then annotated POJOs are converted to XML
@XmlRootElement @Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, quarkus.log.console.enable=true
public class Message { PARAMETER, TYPE_USE }) quarkus.log.console.level=DEBUG
} @Retention(RUNTIME) quarkus.log.console.color=false
@Documented quarkus.log.category."com.lordofthejars".level=DEBUG
@GET @Constraint(validatedBy = { NotExpiredValidator.class})
@Produces(MediaType.APPLICATION_XML) public @interface NotExpired {
public Message hello() {
Pre x is quarkus.log .
return message; String message() default "Sauce must not be expired";
} Class<?>[] groups() default { }; category."<category-name>".level
Class<? extends Payload>[] payload() default { };
Minimum level category (default: INFO )

}
Validator level
Default minimum level (default: INFO )
Quarkus uses Hibernate Validator to validate input/output of REST
services and business services using Bean validation spec. You need to implement the validator logic in a class that
console.enabled
implements ConstraintValidator .
Console logging enabled (default: true )
./mvnw quarkus:add-extension
public class NotExpiredValidator
-Dextensions="io.quarkus:quarkus-hibernate-validator" console.format
implements ConstraintValidator<NotExpired, LocalDate>
{ Format pattern to use for logging. Default value:
%d{yyyy-MM-dd HH:mm:ss,SSS} %-5p [%c{3.}] (%t) %s%e%n
Annotate POJO objects with validator annotations such as: @Override
@NotNull , @Digits , @NotBlank , @Min , @Max , … public boolean isValid(LocalDate value, console.level
ConstraintValidatorContext ctx) { Minimum log level (default: INFO )
public class Sauce { if ( value == null ) return true;
LocalDate today = LocalDate.now(); console.color
@NotBlank(message = "Name may not be blank") return ChronoUnit.YEARS.between(today, value) > 0;
Allow color rendering (default: true )
private String name; }
@Min(0) }
file.enable
private long scovilleHeatUnits;
File logging enabled (default: false )
// getter/setters And use it normally:
} file.format
Format pattern to use for logging. Default value:
@NotExpired
%d{yyyy-MM-dd HH:mm:ss,SSS} %h %N[%i] %-5p [%c{3.}] (%t) %s%e%n
@JsonbDateFormat(value = "yyyy-MM-dd")
To validate an object use @Valid annotation: private LocalDate expired;
file.level

public Response create(@Valid Sauce sauce) {} Minimum log level (default: ALL )
Manual Validation
file.path

You can call the validation process manually instead of relaying to The path to log le (default: quarkus.log )
If a validation error is triggered, a violation report is
@Valid by injecting Validator class.
generated and serialized as JSON. If you want to
file.rotation.max-file-size
manipulate the output, you need to catch in the code the
ConstraintViolationException exception. @Inject The maximum le size of the log le
Validator validator;
Create Your Custom Constraints file.rotation.max-backup-index
The maximum number of backups to keep (default: 1 )
First you need to create the custom annotation:
And use it:
file.rotation.file-suffix

Set<ConstraintViolation<Sauce>> violations = Rotating log le su x.


validator.validate(sauce);
file.rotation.rotate-on-boot
Indicates rotate logs at bootup (default: true )
Logging
file.async

You can con gure how Quarkus logs: Log asynchronously (default: false )

file.async.queue-length
The queue length to use before ushing writing (default: 512 )
file.async.overflow
./mvnw quarkus:add-extension public class WorldClockOptions {
Action when queue is full (default: BLOCK ) -Dextensions="quarkus-logging-json" @HeaderParam("Authorization")
String auth;
syslog.enable
syslog logging is enabled (default: false ) And the con guration values are pre x with quarkus.log : @PathParam("where")
String where;
syslog.format json }

The format pattern to use for logging to syslog. Default value: JSON logging is enabled (default: true).
%d{yyyy-MM-dd HH:mm:ss,SSS} %h %N[%i] %-5p [%c{3.}] (%t) %s%e%n
json.pretty-print And con gure the hostname at application.properties :
syslog.level JSON output is "pretty-printed" (default: false)
The minimum log level to write to syslog (default: ALL ) org.acme.quickstart.WorldClockService/mp-rest/url=
json.date-format http://worldclockapi.com
syslog.endpoint Specify the date format to use (default: the default format)
The IP address and port of the syslog server (default:
localhost:514 ) json.record-delimiter Injecting the client:
Record delimiter to add (default: no delimiter)
syslog.app-name @RestClient
The app name used when formatting the message in RFC5424 json.zone-id WorldClockService worldClockService;
format (default: current process name) The time zone ID
syslog.hostname
json.exception-output-type If invokation happens within JAX-RS, you can propagate headers
The name of the host the messages are being sent from (default: The exception output type: detailed , formatted , detailed-and-
from incoming to outgoing by using next property.
current hostname) formatted (default: detailed )
org.eclipse.microprofile.rest.client.propagateHeaders=
syslog.facility Authorization,MyCustomHeader
json.print-details
Priority of the message as de ned by RFC-5424 and RFC-3164 Detailed caller information should be logged (default: false)
(default: USER_LEVEL )

syslog.syslog-type
Rest Client You can still use the JAX-RS client without any problem
ClientBuilder.newClient().target(…
)
The syslog type of format message (default: RFC5424 )
Quarkus implements MicroPro le Rest Client spec:
Adding headers
syslog.protocol
./mvnw quarkus:add-extension You can customize the headers passed by implementing
Protocol used (default: TCP ) -Dextensions="quarkus-rest-client" MicroPro le ClientHeadersFactory annotation:
syslog.use-counting-framing
@RegisterForReflection
Message pre xed with the size of the message (default false )
To get content from http://worldclockapi.com/api/json/cet/now public class BaggageHeadersFactory
you need to create a service interface: implements ClientHeadersFactory {
syslog.truncate
@Override
Message should be truncated (default: true ) @Path("/api") public MultivaluedMap<String, String> update(
@RegisterRestClient MultivaluedMap<String, String> incomingHeaders,
syslog.block-on-reconnect MultivaluedMap<String, String> outgoingHeaders) {}
public interface WorldClockService {
Block when attempting to reconnect (default: true ) }
@GET @Path("/json/cet/now")
syslog.async @Produces(MediaType.APPLICATION_JSON)
Log asynchronously (default: false ) WorldClock getNow(); And registering it in the client using RegisterClientHeaders
annotation.
syslog.async.queue-length
@GET
@Path("/json/{where}/now")
The queue length to use before ushing writing (default: 512 ) @Produces(MediaType.APPLICATION_JSON)
@RegisterClientHeaders(BaggageHeadersFactory.class)
@RegisterRestClient
WorldClock getSauce(@BeanParam
syslog.async.overflow public interface WorldClockService {}
WorldClockOptions worldClockOptions);
Action when queue is full (default: BLOCK )
}
JSON output Or statically set:

You can con gure the output to be in JSON format instead of plain
text.
@GET import org.acme.quickstart.WorldClockService/mp-rest/connectTimeou
@ClientHeaderParam(name="X-Log-Level", value="ERROR") org.jboss.resteasy.annotations.providers.multipart.Mult t=
Response getNow(); ipartForm; 1000
org.acme.quickstart.WorldClockService/mp-rest/readTimeout=
@Path("/echo") 2000
@RegisterRestClient
Asynchronous
public interface MultipartService {
A method on client interface can return a CompletionStage class to
be executed asynchronously. @POST Testing
@Consumes(MediaType.MULTIPART_FORM_DATA)
@Produces(MediaType.TEXT_PLAIN) Quarkus archetype adds test dependencies with JUnit 5 and Rest-
@GET @Path("/json/cet/now") Assured library to test REST endpoints.
String sendMultipartData(@MultipartForm
@Produces(MediaType.APPLICATION_JSON)
MultipartBody data);
CompletionStage<WorldClock> getNow();
@QuarkusTest
} public class GreetingResourceTest {

Multipart @Test
public void testHelloEndpoint() {
It is really easy to send multipart form-data with Rest Client. SSL
given()
You can con gure Rest Client key stores. .when().get("/hello")
<dependency> .then()
<groupId>org.jboss.resteasy</groupId> .statusCode(200)
org.acme.quickstart.WorldClockService/mp-rest/trustStore=
<artifactId>resteasy-multipart-provider</artifactId> .body(is("hello"));
classpath:/store.jks
</dependency> }
org.acme.quickstart.WorldClockService/mp-rest/trustStorePas
}
sword=
supersecret
The model object:
Test port can be set in quarkus.http.test-port property.
import java.io.InputStream; Possible con guration properties: You can also inject the URL where Quarkus is started:

import javax.ws.rs.FormParam; %s/mp-rest/trustStore
import javax.ws.rs.core.MediaType; @TestHTTPResource("index.html")
Trust store location de ned with classpath: or file: pre x.
URL url;
import
%s/mp-rest/trustStorePassword
org.jboss.resteasy.annotations.providers.multipart.Part
Type; Trust store password.
Quarkus Test Resource

%s/mp-rest/trustStoreType
public class MultipartBody { You can execute some logic before the rst test run ( start ) and
Trust store type (default: JKS ) execute some logic at the end of the test suite ( stop ).
@FormParam("file")
@PartType(MediaType.APPLICATION_OCTET_STREAM) %s/mp-rest/hostnameVerifier You need to create a class implementing
private InputStream file; QuarkusTestResourceLifecycleManager interface and register it in the
Custom hostname veri er class name.
test via @QuarkusTestResource annotation.
@FormParam("fileName")
%s/mp-rest/keyStore
@PartType(MediaType.TEXT_PLAIN)
private String name; Key store location de ned with classpath: or file: pre x.

// getter/setters %s/mp-rest/keyStorePassword
} Key store password.

%s/mp-rest/keyStoreType

And the Rest client interface: Key store type (default: JKS )

Timeout

You can de ne the timeout of the Rest Client:


public class MyCustomTestResource @QuarkusTest Persistence
implements QuarkusTestResourceLifecycleManager { @Stereotype
@Transactional Quarkus works with JPA(Hibernate) as persistence solution. But
@Override @Retention(RetentionPolicy.RUNTIME) also provides an Active Record pattern implementation under
public Map<String, String> start() { @Target(ElementType.TYPE) Panache project.
// return system properties that public @interface TransactionalQuarkusTest {
// should be set for the running test } To use database access you need to add Quarkus JDBC drivers
return Collections.emptyMap(); instead of the original ones. At this time Apache Derby , H2 , MariaDB ,
} @TransactionalQuarkusTest MySQL , MSSQL and PostgreSQL drivers are supported.
public class TestStereotypeTestCase {}
@Override ./mvnw quarkus:add-extension
public void stop() { -Dextensions="io.quarkus:quarkus-hibernate-orm-panache,
} io.quarkus:quarkus-jdbc-mariadb"
Test Coverage Due the nature of Quarkus to calculate correctly the

coverage information with JaCoCo, you might need o ine
// optional
instrumentation. I recommend reading this document to
@Override
understand how JaCoCo and Quarkus works and how you can
public void inject(Object testInstance) { @Entity
con gure JaCoCo to get correct data.
} public class Developer extends PanacheEntity {

Native Testing
// optional // id field is implicit
@Override To test native executables annotate the test with @NativeImageTest .
public int order() { public String name;
return 0; }
}
}
And con guration in src/main/resources/application.properties :

Returning new system properties implies running parallel quarkus.datasource.url=jdbc:mariadb://localhost:3306/mydb


tests in different JVMs. quarkus.datasource.driver=org.mariadb.jdbc.Driver
quarkus.datasource.username=developer
And the usage: quarkus.datasource.password=developer
quarkus.hibernate-orm.database.generation=update

@QuarkusTestResource(MyCustomTestResource.class)
public class MyTest {
} List of datasource parameters.

quarkus.datasource as pre x is skipped in the next table.


Mocking
Parameter Type
If you need to provide an alternative implementation of a service
driver String
(for testing purposes) you can do it by using CDI @Alternative
annotation using it in the test service placed at src/test/java :
url String
@Alternative
@Priority(1)
@ApplicationScoped username String
public class MockExternalService extends ExternalService {}

password String

This does not work when using native image testing.


min-size Integer

A stereotype annotation io.quarkus.test.Mock is provided declaring


@Alternative , @Priority(1) and @Dependent . max-size Integer

Interceptors
initial-size Integer
Tests are actually full CDI beans, so you can apply CDI interceptors:

background-validation-interval java.time.Duration
Parameter Type Parameter Description Values[Default] // Insert
Developer developer = new Developer();
acquisition-timeout java.time.Duration [ none ], create , drop- developer.name = "Alex";
Database schema
database.generation and-create , drop , developer.persist();
is generation.
update .
leak-detection-interval java.time.Duration // Find All
Developer.findAll().list();
Stop on the rst
idle-removal-interval java.time.Duration database.generation.halt- error when
[ flase ], true // Find By Query
on-error applying the Developer.find("name", "Alex").firstResult();
schema.
io.quarkus.agroal.runtime
transaction-isolation-level // Delete
.TransactionIsolationLevel
Developer developer = new Developer();
database.default-catalog Default catalog. developer.id = 1;
developer.delete();
enable-metrics Boolean

database.default-schema Default Schema.
// Delete By Query
xa Boolean
long numberOfDeleted = Developer.delete("name", "Alex");

database.charset Charset.

validation-query-sql Boolean Remember to annotate methods with @Transactional annotation to


Time Zone JDBC make changes persisted in the database.
jdbc.timezone
driver.
Hibernate con guration properties. Pre x quarkus.hibernate-orm is If queries start with the keyword from then they are treated as HQL
skipped. query, if not then next short form is supported:
jdbc.statement-fetch- Number of rows
Parameter Description Values[Default] size fetched at a time. order by which expands to from EntityName order by …

Class name of the <columnName> which expands to from EntityName where


Not necessary to
dialect Hibernate ORM jdbc.statement-batch- Number of updates <columnName>=?
set.
dialect. size sent at a time.
<query> which is expanded to from EntityName where <query>

The storage engine log.sql Show SQL logs [ false ], true Static Methods
when the dialect Not necessary to
dialect.storage-engine findById :`Object`
supports multiple set.
storage engines. Collect and show Returns object or null if not found. Overloaded version with
log.jdbc-warnings [ false ], true LockModeType is provided.
JDBC warnings.

Name of the le findByIdOptional :`Optional<Object>`


containing the SQL Enable statiscs Returns object or java.util.Optional .
statistics [ false ], true
statements to collection.
sql-load-script execute when import.sql find :`String`, [ Object… , Map<String, Object> , Parameters ]
starts. no-file
Database operations: Lists of entities meeting given query with parameters set.
force Hibernate to
skip SQL import.
find :`String`, Sort , [ Object… , Map<String, Object> , Parameters ]
Lists of entities meeting given query with parameters set sorted
The size of the by Sort attribute/s.
batch-fetch-size -1 disabled.
batches.
findAll
Finds all entities.
The maximum size
query.query-plan-cache-
of the query plan
max-size findAll :`Sort`
cache.
Finds all entities sorted by Sort attribute/s.

Default stream :`String`, [ Object… , Map<String, Object> , Parameters ]


query.default-null-
precedence of null [ none ], first , last . java.util.stream.Stream of entities meeting given query with
ordering
values in ORDER BY . parameters set.

stream :`String`, Sort , [ Object… , Map<String, Object> , Parameters ]


java.util.stream.Stream
of entities meeting given query with You can inject then AgroalDataSource with
<plugin>
parameters set sorted by Sort attribute/s. <groupId>org.jboss.jandex</groupId>
io.quarkus.agroal.DataSource .

<artifactId>jandex-maven-plugin</artifactId>
streamAll @DataSource("users")
<version>1.0.3</version>
java.util.stream.Stream of all entities. <executions> AgroalDataSource dataSource1;
<execution>
streamAll :`Sort` <id>make-index</id>
java.util.stream.Stream of all entities sorted by Sort attribute/s. <goals> Flushing
<goal>jandex</goal>
count
</goals> You can force ush operation by calling .flush() or
</execution> .persistAndFlush() to make it in a single call.
Number of entities.
</executions>
<dependencies> This ush is less e cient and you still need to commit
count :`String`, [ Object… , Map<String, Object> , Parameters ]
<dependency> transaction.
Number of entities meeting given query with parameters set. <groupId>org.jboss</groupId>
<artifactId>jandex</artifactId>
Testing
deleteAll <version>2.1.1.Final</version>
Number of deleted entities. </dependency> There is a Quarkus Test Resource that starts and stops H2 server
</dependencies> before and after test suite.
delete :`String`, [ Object… , Map<String, Object> , Parameters ]
</plugin>
Register dependency io.quarkus:quarkus-test-h2:test .
Number of deleted entities meeting given query with parameters
set. And annotate the test:
DAO pattern
persist :[ Iterable , Steram , Object… ]
Also supports DAO pattern with PanacheRepository<TYPE> . @QuarkusTestResource(H2DatabaseTestResource.class)
TIP: find methods de nes a withLock(LockModeType) to de ne the public class FlywayTestResources {
lock type and withHint(QueryHints.HINT_CACHEABLE, "true") to }
@ApplicationScoped
de ne hints.
public class DeveloperRepository
implements PanacheRepository<Person> {
Pagination
public Person findByName(String name){ Transactions
return find("name", name).firstResult();
PanacheQuery<Person> livingPersons = Person } The easiest way to de ne your transaction boundaries is to use the
.find("status", Status.Alive); } @Transactional annotation.
livingPersons.page(Page.ofSize(25));
Transactions are mandatory in case of none idempotent
// get the first page operations.
List<Person> firstPage = livingPersons.list(); EntityManager You can inject EntityManager in your classes:
// get the second page @Transactional
List<Person> secondPage = livingPersons.nextPage().list(); @Inject
public void createDeveloper() {}
EntityManager em;

em.persist(car);
If entities are de ned in external JAR, you need to enable in these You can control the transaction scope:
projects the Jandex plugin in project.
@Transactional(REQUIRED) (default): starts a transaction if none
Multiple datasources was started, stays with the existing one otherwise.
You can register more than one datasource. @Transactional(REQUIRES_NEW) : starts a transaction if none was
started; if an existing one was started, suspends it and starts a
# default new one for the boundary of that method.
quarkus.datasource.driver=org.h2.Driver
quarkus.datasource.url=jdbc:h2:tcp://localhost/mem:default @Transactional(MANDATORY) : fails if no transaction was started ;
.... works within the existing transaction otherwise.
# users datasource
quarkus.datasource.users.driver=org.h2.Driver @Transactional(SUPPORTS) : if a transaction was started, joins it ;
quarkus.datasource.users.url=jdbc:h2:tcp://localhost/mem:us otherwise works with no transaction.
ers
@Transactional(NOT_SUPPORTED) :
if a transaction was started,
suspends it and works with no transaction for the boundary of
the method; otherwise works with no transaction.
Notice that after datasource you set the datasource name, in
previous case users . @Transactional(NEVER) : if a transaction was started, raises an
exception; otherwise works with no transaction.
You can con gure the default transaction timeout using User written based
public class AuthorMarshaller
quarkus.transaction-manager.default-transaction-timeout
implements MessageMarshaller<Author> {
con guration property. By default it is set to 60 seconds. There are three ways to create your schema:

Proto le @Override
You can set a timeout property, in seconds, that applies to
public String getTypeName() {
transactions created within the annotated method by using
@TransactionConfiguration annotation. Creates a .proto le in the META-INF directory. return "book_sample.Author";
}

@Transactional package book_sample;
@Override
@TransactionConfiguration(timeout=40)
public Class<? extends Author> getJavaClass() {
public void createDeveloper() {} message Author {
return Author.class;
required string name = 1;
}
required string surname = 2;

}
If you want more control over transactions you can inject @Override
UserTransaction and use a programmatic way. public void writeTo(ProtoStreamWriter writer,
Author author) throws IOException {
In case of having a Collection eld you need to use the repeated key writer.writeString("name", author.getName());
@Inject UserTransaction transaction
(ie repeated Author authors = 4 ). writer.writeString("surname", author.getSurname());

}
transaction.begin(); In code
transaction.commit();
@Override
transaction.rollback(); Setting proto schema directly in a produced bean.
public Author readFrom(ProtoStreamReader reader)
throws IOException {
@Produces String name = reader.readString("name");
In nispan FileDescriptorSource bookProtoDefinition() { String surname = reader.readString("surname");
return FileDescriptorSource return new Author(name, surname);
.fromString("library.proto",
Quarkus integrates with In nispan: }
"package book_sample;\n" + }
"message Author {\n" +
./mvnw quarkus:add-extension " required string name = 1;\n" +
-Dextensions="infinispan-client" " required string surname = 2;\n" +
"}");
And producing the marshaller:
}
Serialization uses a library called Protostream. @Produces
MessageMarshaller authorMarshaller() {
Annotation based return new AuthorMarshaller();
Marshaller }
@ProtoFactory Using org.infinispan.protostream.MessageMarshaller interface.
public Author(String name, String surname) {
this.name = name; In nispan Embedded
this.surname = surname;
}
./mvnw quarkus:add-extension

-Dextensions="infinispan-embeddedy"
@ProtoField(number = 1)
public String getName() {
return name;
}

@ProtoField(number = 2)
public String getSurname() {
return surname;
}

Initializer to set con guration settings.

@AutoProtoSchemaBuilder(includeClasses =
{ Book.class, Author.class },
schemaPackageName = "book_sample")
interface BookContextInitializer
extends SerializationContextInitializer {
}
flyway.locations You need to annotate your model with Hibernate Search API to
Con guration in infinispan.xml : CSV locations to scan recursively for migrations. Supported index it:
pre xes classpath and filesystem (default:
<local-cache name="quarkus-transaction"> classpath:db/migration ). @Entity
<transaction @Indexed
transaction-manager-lookup= flyway.connect-retries public class Author extends PanacheEntity {
"org.infinispan.transaction.lookup.JBossStandaloneJ
The maximum number of retries when attempting to connect
TAManagerLookup"/> @FullTextField(analyzer = "english")
(default: 0)
</local-cache> public String bio;

flyway.schemas
@FullTextField(analyzer = "name")
CSV case-sensitive list of schemas managed (default: none) @KeywordField(name = "firstName_sort",
Set con guration le location in application.properties :
sortable = Sortable.YES,
a| flyway.table normalizer = "sort")
quarkus.infinispan-embedded.xml-config=infinispan.xml
The name of Flyway’s schema history table (default: public String firstName;
flyway_schema_history )
@OneToMany
And you can inject the main entry point for the cache: flyway.sql-migration-prefix @IndexedEmbedded
Pre x for versioned SQL migrations (default: V ) public List<Book> books;
@Inject
}
org.infinispan.manager.EmbeddedCacheManager cacheManager; flyway.repeatable-sql-migration-prefix:: Pre x for repeatable SQL
migrations (default: R )

flyway.baseline-on-migrate
Flyway Only migrations above baseline-version will then be applied It is not mandatory to use Panache.

Quarkus integrates with Flyway to help you on database schema


migrations.
flyway.baseline-version You need to de ne the analyzers and normalizers de ned in
Version to tag an existing schema with when executing baseline annotations. You only need to implement
(default: 1) ElasticsearchAnalysisConfigurer interface and con gure it.
./mvnw quarkus:add-extension
-Dextensions="quarkus-flyway"
flyway.baseline-description public class MyQuarkusAnalysisConfigurer
Description to tag an existing schema with when executing implements ElasticsearchAnalysisConfigurer {
baseline (default: Flyway Baseline )
Then place migration les to the migrations folder @Override
( classpath:db/migration ). public void configure(
Multiple Datasources
ElasticsearchAnalysisDefinitionContainerContext ct
You can inject org.flywaydb.core.Flyway to programmatically
execute the migration. To use multiple datasource in Flyway you just need to add the x)
datasource name just after the flyway property: {
ctx.analyzer("english").custom()
@Inject .withTokenizer("standard")
quarkus.datasource.users.url=jdbc:h2:tcp://localhost/mem:us
Flyway flyway; .withTokenFilters("asciifolding",
ers
"lowercase", "porter_stem");
quarkus.datasource.inventory.url=jdbc:h2:tcp://localhost/me
flyway.migrate();
m:inventory
ctx.normalizer("sort").custom()
# ...
.withTokenFilters("asciifolding", "lowercase");

Or can be automatically executed by setting migrate-at-start }
quarkus.flyway.users.schemas=USERS_TEST_SCHEMA
property to true . }
quarkus.flyway.inventory.schemas=INVENTORY_TEST_SCHEMA
# ...
quarkus.flyway.migrate-at-start=true
Use Hibernate Search in REST service:
Hibernate Search
List of Flyway parameters.
Quarkus integrates with Elasticsearch to provide a full-featured full-
quarkus. as pre x is skipped in the next table. text search using Hibernate Search API.
flyway.clean-at-start
./mvnw quarkus:add-extension
Execute Flyway clean command (default: false )
-Dextensions="quarkus-hibernate-search-elasticsearch"

flyway.migrate-at-start
Flyway migration automatically (default: false )
public class LibraryResource { Parameter Description Parameter Description

@Inject username Username for auth. @Indexed Register entity as full text index
EntityManager em;

@Transactional password Password for auth. Full text search. Need to set an
@FullTextField
public List<Author> searchAuthors( analyzer to split tokens.
@QueryParam("pattern") String pattern) {
connection-timeout Duration of connection timeout.
return Search.getSearchSession(em)
The string is kept as one single
.search(Author.class) @KeywordField
.predicate(f ->
token but can be normalized.
Max number of connections to
pattern == null || pattern.isEmpty() ? max-connections
servers.
f.matchAll() :
Include the Book elds into the
f.simpleQueryString() IndexedEmbedded
Author index.
.onFields("firstName",
Max number of connections to
"lastName", "books.title") max-connections-per-route
server.
.matching(pattern)
Sets how to extract a value from
) @ContainerExtraction
container, e.g from a Map .
.sort(f -> f.byField("lastName_sort") indexes Per-index speci c con guration.
.then().byField("firstName_sort"))
.fetchHits(); Map an unusual entity identi er
@DocumentId
} discovery.enabled Enables automatic discovery. to a document identi er.

discovery.refresh-interval Refresh interval of node list. Full text index for any supported
When not using Hibernate ORM, index data using @GenericField
Search.getSearchSession(em).createIndexer()
type.
.startAndWait() at startup time.
Scheme to be used for the new
discovery.default-scheme
nodes. Reference to the identi er bridge
Con gure the extension in application.properties : @IdentifierBridgeRef
to use for a @DocumentId .

quarkus.hibernate-search.elasticsearch.version=7 Status for which you wait before


automatic-
quarkus.hibernate-search.elasticsearch. considering the operation How a dependency of the
indexing.synchronization-
analysis-configurer=MyQuarkusAnalysisConfigurer completed ( queued , committed or indexing process to a property
strategy @IndexingDependency
quarkus.hibernate-search.elasticsearch. searchable ). should affect automatic
automatic-indexing.synchronization-strategy=searchable reindexing.
quarkus.hibernate-search.elasticsearch.
index-defaults.lifecycle.strategy=drop-and-create When enabled, re-indexing of is
quarkus.hibernate-search.elasticsearch. automatic-indexing.enable-dirty- skipped if the changes are on @ObjectPath
index-defaults.lifecycle.required-status=yellow check properties that are not used
when indexing.
For java.math.BigDecimal or
@ScaledNumberField java.math.BigInteger that you
List of Hibernate-Elasticsearch properties pre xed with
Index lifecycle ( none , validate , need higher precision.
quarkus.hibernate-search.elasticsearch : index-
update , create , drop-and-create ,
defaults.lifecycle.strategy
drop-abd-create-drop )
Parameter Description
Amazon DynamoDB
Map of con guration of index-
backends
additional backends. Minimal cluster status ( green , Quarkus integrates with Amazon DynamoDB:
defaults.lifecycle.required-
yellow , red )
status
./mvnw quarkus:add-extension
version Version of Elasticsearch -Dextensions="quarkus-amazon-dynamodb"
index-
Waiting time before failing the
defaults.lifecycle.required-
Class or name of the neab used bootstrap.
analysis-configurer status-wait-timeout
to con gure. @Inject
DynamoDbClient dynamoDB;
index-defaults.refresh-after- Set if index should be refreshed
List of Elasticsearch servers @Inject
hosts write after writes.
hosts. DynamoDbAsyncClient dynamoDB;

Possible annotations:
l l
quarkus.dynamodb.region= Parameter Default Description Parameter Default Description
eu-central-1
quarkus.dynamodb.endpoint-override= Credentials that The amount of time
process-
http://localhost:8000 should be used between credentials
provider.credential- PT15S
quarkus.dynamodb.credentials.type=STATIC DEFAULT , STATIC , expire and
refresh-threshold
quarkus.dynamodb.credentials.static-provider SYSTEM_PROPERTY , credentials refreshed.
credentials.type DEFAULT
.access-key-id=test-key ENV_VARIABLE ,
quarkus.dynamodb.credentials.static-provider PROFILE , CONTAINER ,
.secret-access-key=test-secret INSTANCE_PROFILE , process-
PROCESS , ANONYMOUS provider.async- Should fetch
false
credential-update- credentials async.
enabled
If you want to work with an AWS account, you’d need to set it with: Credentials speci c parameters pre xed with
quarkus.dynamodb.aws.credentials :
quarkus.dynamodb.region=<YOUR_REGION> In case of synchronous client, the next parameters can be
quarkus.dynamodb.credentials.type=DEFAULT Parameter Default Description con gured pre xed by quarkus.dynamodb.sync-client :

DEFAULT Parameter Default Description


DEFAULT credentials provider chain:
connection- Connection
10S
System properties aws.accessKeyId , aws.secretKey default- acquisition-timeout acquisation timeout.
provider.async- Should fetch
false
Env. Varables AWS_ACCESS_KEY_ID , AWS_SECRET_ACCESS_KEY credential-update- credentials async.
enabled Max time to
connection-max-idle-
Credentials pro le ~/.aws/credentials 60S connection to be
time
opened.
Credentials through the Amazon EC2 container service if the default- Should reuse the last
AWS_CONTAINER_CREDENTIALS_RELATIVE_URI set provider.reuse-last- true successful
provider-enabled credentials. connection-timeout Connection timeout.
Credentials through Amazon EC2 metadata service.

Con guration parameters pre xed with quarkus.dynamodb : STATIC connection-time-to- Max time connection
0
live to be open.

Parameter Default Description static-


provider.access-key- AWS access key id. socket-timeout 30S Time to wait for data.
id
Endpoint discovery
enable-endpoint- for a service API that max-connections 50 Max connections.
false
discovery supports endpoint static-
discovery. AWS secret access
provider.secret-
key. Client send an HTTP
access-key expect-continue-
true expect-continue
enabled
Con gure the handsake.
endpoint with which PROFILE
endpoint-override
the SDK should
communicate. Connections in pool
use-idle-connection-
profile- The name of the true should be closed
default reaper
provider.profile-name pro le to use. asynchronously.
Time to complete an
api-call-timeout
execution.
PROCESS Endpoint of the proxy
proxy.endpoint
server.
List of class
interceptors
interceptors. Command to execute
process-
to retrieve proxy.enabled false Enables HTTP proxy.
provider.command
credentials.
Con guration parameters pre xed with quarkus.dynamodb.aws :
proxy.username Proxy username.
Parameter Default Description process-
Max bytes to retrieve
provider.process- 1024
from process. Proxy password.
Region that hosts output-limit proxy.password
region
DynamoDB.
Parameter Default Description Parameter Default Description Parameter Default Description

For NTLM, domain Connections in pool event-loop.thread- aws-java-sdk- Pre x of thread


proxy.ntlm-domain use-idle-connection-
name. true should be closed name-prefix NettyEventLoop names.
reaper
asynchronously.

proxy.ntlm- For NTLM, Neo4j


workstation workstation name. read-timeout 30S Read timeout.
Quarkus integrates with Neo4j:
proxy.preemptive- write-timeout 30S Write timeout.
Authenticate pre- ./mvnw quarkus:add-extension
basic-authentication-
emptively. -Dextensions="quarkus-neo4j"
enabled
Endpoint of the proxy
proxy.endpoint
server.
proxy.non-proxy- List of non proxy
hosts hosts. @Inject
proxy.enabled false Enables HTTP proxy. org.neo4j.driver.Driver driver;

TLS manager: none ,


tls-managers-
system-property system-property , proxy.non-proxy- List of non proxy Con guration properties:
provider.type
file-store hosts hosts.
quarkus.neo4j as pre x is skipped in the next table.

tls-managers- TLS manager: none , Parameter Default Description


tls-managers-
provider.file- Path to key store. system-property system-property ,
provider.type
store.path file-store uri localhost:7687 URI of Neo4j.

tls-managers- tls-managers- authentication


provider.file- Key store type. provider.file- Path to key store. neo4j Username.
.username
store.type store.path

authentication
tls-managers- tls-managers- neo4j Password.
.password
provider.file- Key store password. provider.file- Key store type.
store.password store.type
authentication Disable
false
.disabled authentication.
In case of asynchronous client, the next parameters can be tls-managers-
con gured pre xed by quarkus.dynamodb.async-client : provider.file- Key store password.
store.password pool.metrics-enabled false Enable metrics.
Parameter Default Description

connection- Connection SSL Provider ( jdk , pool.log-leaked- Enable leaked


10S false
acquisition-timeout acquisation timeout. ssl-provider openssl , openssl- sessions sessions logging.
refcnt ).

Max time to pool.max-connection- Max amount of


connection-max-idle- 100
60S connection to be Sets the HTTP pool-size connections.
time protocol HTTP_1_1
opened. protocol.

Pooled connections
connection-timeout Connection timeout. Max number of pool.max-connection- older will be closed
max-http2-streams 1H
concurrent streams. lifetime and removed from
the pool.
connection-time-to- Max time connection
0
live to be open. Enable custom event
event-loop.override false
loop conf. Timout for
pool.connection-
1M connection
acquisition-timeout
Max number of adquisation.
max-concurrency 50 concurrent event-loop.number-of- Number of threads to
connections. threads use in event loop.
Parameter Default Description @Inject Parameter Type Description
com.mongodb.client.MongoClient client;
Pooled connections connection-timeout Duration
pool.idle-time- idled in the pool for @Inject
before-connection- -1 longer than this io.quarkus.mongodb.ReactiveMongoClient client;
test timeout will be tested socket-timeout Duration
before they are used.

quarkus.mongodb.connection-string=mongodb://localhost:27018 tls-insecure boolean [false] Insecure TLS.


As Neo4j uses SSL communication by default, to create a native quarkus.mongodb.write-concern.journal=false
executable you need to compile with next options GraalVM options:
tls boolean [false] Enable TLS
-H:EnableURLProtocols=http,https --enable-all-security-services -
H:+JNI quarkus.mongodb as pre x is skipped in the next table.
Implies hosts given
replica-set-name String
And Quarkus Maven Plugin with next con guration: Parameter Type Description are a seed list.

<artifactId>quarkus-maven-plugin</artifactId> MongoDB connection


connection-string String
<executions> URI. server-selection- Time to wait for
Duration
<execution> timeout server selection.
<id>native-image</id>
Addresses passed as
<goals> hosts List<String>
host:port . Minimum ping time
<goal>native-image</goal>
local-threshold Duration to make a server
</goals>
<configuration>
eligible.
application-name String Application name.
<enableHttpUrlHandler>true
</enableHttpUrlHandler>
Frequency to
<enableHttpsUrlHandler>true
Maximum number of heartbeat-frequency Duration determine the state
</enableHttpsUrlHandler> max-pool-size Int
connections. of servers.
<enableAllSecurityServices>true
</enableAllSecurityServices>
<enableJni>true</enableJni> Minimum number of primary ,
</configuration> min-pool-size Int
connections. primaryPreferred ,
</execution>
read-preference secondary , Read preferences.
</executions>
secondaryPreferred ,
max-connection-idle- Idle time of a pooled nearest
Duration
time connection.
Alternatively, and as a not recommended way in production, you
can disable SSL and Quarkus will disable Bolt SSL as well. Max number of
quarkus.ssl.native=false .
max-connection-life- Life time of pooled concurrent
Duration max-wait-queue-size Int
time connection. operations allowed to
If you are using Neo4j 4.0, you can use fully reactive. Add next wait.
depenency management io.projectreactor:reactor-
bom:Californium-SR4:pom:import and dependency: Maximum wait time
wait-queue-timeout Duration
io.projectreactor:reactor-core . for new connection. Ensures are writes
write-concern.safe boolean [true]
are ack.
public Publisher<String> get() {
Time period between
return Flux.using(driver::rxSession, ...); maintenance-
Duration runs of maintenance write- Journal writing
} frequency boolean [true]
job. concern.journal aspect.

Time to wait before


MongoDB Client maintenance-initial-
running the rst write-concern.w String
Value to all write
delay
Duration commands.
maintenance job.
Quarkus integrates with MongoDB:
write-concern.retry- Retry writes if
boolean [false]
./mvnw quarkus:add-extension Multiplied with max- writes network fails.
-Dextensions="quarkus-mongodb-client" pool-size gives max
wait-queue-multiple Int
numer of threads
waiting. write-concern.w- Timeout to all write
Duration
timeout commands.
Parameter Type Description person.persist(); <plugin>
person.update(); <groupId>org.jboss.jandex</groupId>
credentials.username String Username. person.delete(); <artifactId>jandex-maven-plugin</artifactId>
<version>1.0.3</version>
List<Person> allPersons = Person.listAll(); <executions>
credentials.password String Password. person = Person.findById(personId); <execution>
List<Person> livingPersons = Person.list("status", Status.A <id>make-index</id>
live); <goals>
credentials.auth- MONGO-CR , GSSAPI ,
List<Person> persons = Person.list(Sort.by("name").and("bir <goal>jandex</goal>
mechanism PLAIN , MONGODB-X509
th")); </goals>
</execution>
long countAll = Person.count(); </executions>
Source of the
credentials.auth- <dependencies>
String authentication
source Person.delete("status", Status.Alive); <dependency>
credentials.
<groupId>org.jboss</groupId>
<artifactId>jandex</artifactId>
<version>2.1.1.Final</version>
Authentication All list methods have equivalent stream versions.
credentials.auth- </dependency>
Map<String, String> mechanism
mechanism-properties </dependencies>
properties. Pagination
</plugin>
You can also use pagination:
MongoDB Panache
PanacheQuery<Person> livingPersons =
You can also use the Panache framework to write persistence part Person.find("status", Status.Alive);
when using MongoDB. livingPersons.page(Page.ofSize(25));

// get the first page
./mvnw quarkus:add-extension
List<Person> firstPage = livingPersons.list();
-Dextensions="mongodb-panache"
// get the second page
List<Person> secondPage = livingPersons.nextPage().list();

MongoDB con guration comes from MongoDB Client section.


Queries
@MongoEntity(collection="ThePerson")
public class Person extends PanacheMongoEntity { Native MongoDB queries are supported (if they start with { or
public String name; org.bson.Document instance) as well as Panache Queries. Panache
Queries equivalence in MongoDB:
@BsonProperty("birth")
public LocalDate birthDate; firstname = ?1 and status = ?2 → {'firstname': ?1, 'status': ?
2}
public Status status;
} amount > ?1 and firstname != ?2 → {'amount': {'$gt': ?1},
'firstname': {'$ne': ?2}}

lastname like ?1 → {'lastname': {'$regex': ?1}}


Possible annotations in elds: @BsonId (for custom ID),
@BsonProperty and @BsonIgnore . lastname is not null → {'lastname':{'$exists': true}}

Important: @MongoEntity is optional.


PanacheQL refers to the Object parameter name but native
Methods provided are similar of the ones shown in Persistence queries refer to MongoDB eld names.
section.
DAO pattern

@ApplicationScoped
public class PersonRepository
implements PanacheMongoRepository<Person> {
}

If entities are de ned in external JAR, you need to enable in these


projects the Jandex plugin in project.
Reactive Programming @ApplicationScoped @Inject @Stream(“out”)
public class ProducerData { Publisher<String> result;
Quarkus implements MicroPro le Reactive spec and uses RXJava2
to provide reactive programming model. @Outgoing("my-in-memory") @GET
public Flowable<Integer> generate() { @Produces(SERVER_SENT_EVENTS)
./mvnw quarkus:add-extension return Flowable.interval(5, TimeUnit.SECONDS) public Publisher<String> stream() {
-Dextensions=" .map(tick -> random.nextInt(100)); return result;
io.quarkus:quarkus-smallrye-reactive-streams-operators" } }
}

Asynchronous HTTP endpoint is implemented by returning Java Message → Business Logic


CompletionStage . You can create this class either manually or using If you want to dispatch to all subscribers you can annotate the
MicroPro le Reactive Streams spec: method with @Broadcast . @ApplicationScoped
public class ReceiverMessages {
Consumes generated data from my-in-memory stream.
@GET @Incoming("prices")
@Path("/reactive") public void print(String price) {
@ApplicationScoped }
@Produces(MediaType.TEXT_PLAIN)
public class ConsumerData { }
public CompletionStage<String> getHello() {
@Incoming("my-in-memory")
return ReactiveStreams.of("h", "e", "l", "l", "o")
public void randomNumber(int randomNumber) {
.map(String::toUpperCase)
System.out.println("Received " + randomNumber);
.toList() Possible implementations are:
}
.run()
}
.thenApply(list -> list.toString()); In-Memory
}
If the stream is not con gured then it is assumed to be an in-
You can also inject an stream as a eld: memory stream, if not then stream type is de ned by connector
eld.
Creating streams is also easy, you just need to return Publisher
object. @Inject
Kafka
@Stream("my-in-memory") Publisher<Integer> randomRumbers;

@GET To integrate with Kafka you need to add next extensions:


@Path("/stream")
@Produces(MediaType.SERVER_SENT_EVENTS) mvn quarkus:add-extension
@Inject @Stream("generated-price")
public Publisher<String> publishers() { -Dextensions="
Emitter<String> emitter;
return Flowable io.quarkus:quarkus-smallrye-reactive-messaging-kafka"
.interval(500, TimeUnit.MILLISECONDS)
.map(s -> atomicInteger.getAndIncrement())
.map(i -> Integer.toString(i)); Patterns
} Then @Outgoing , @Incoming or @Stream can be used.
REST API → Message
Kafka con guration schema: mp.messaging.[outgoing|incoming].
{stream-name}.<property>=<value> .
@Inject @Stream(“in”)
Reactive Messaging Emitter<String> emitter; The connector type is smallrye-kafka .

Quarkus relies on MicroPro le Reactive Messaging spec to emitter.send(message);
implement reactive messaging streams. mp.messaging.outgoing.generated-price.connector=
smallrye-kafka
mp.messaging.outgoing.generated-price.topic=
mvn quarkus:add-extension
Message → Message prices
-Dextensions="
mp.messaging.outgoing.generated-price.bootstrap.servers=
io.quarkus:quarkus-smallrye-reactive-messaging"
@Incoming(“in”) localhost:9092
@Outgoing(“out”) mp.messaging.outgoing.generated-price.value.serializer=
public String process(String in) { org.apache.kafka.common.serialization.IntegerSerializer
You can just start using in-memory streams by using @Incoming to }
produce data and @Outgoing to consume data. mp.messaging.incoming.prices.connector=
smallrye-kafka
Produce every 5 seconds one piece of data. mp.messaging.incoming.prices.value.deserializer=
Message → SSE org.apache.kafka.common.serialization.IntegerDeserializ
er
A complete list of supported properties are in Kafka site. For the MQTT
@ApplicationScoped
producer and for consumer
public class TopologyProducer {
To integrate with MQTT you need to add next extensions:
@Produces
JSON-B Serializer/Deserializer
public Topology buildTopology() {
./mvnw quarkus:add-extension org.apache.kafka.streams.StreamsBuilder.StreamsBuil
You can use JSON-B to serialize/deserialize objects. -Dextensions="vertx, smallrye-reactive-streams-operator der
s builder = new StreamsBuilder();
./mvnw quarkus:add-extension smallrye-reactive-messaging" // ...
-Dextensions="quarkus-kafka-client"
builder.stream()
.join()
And add io.smallrye.reactive:smallrye-reactive-messaging-mqtt- // ...
To serialize you can use 1.0:0.0.10 dependency in your build tool. .toStream()
io.quarkus.kafka.client.serialization.JsonbSerializer . .to();
Then @Outgoing , @Incoming or @Stream can be used. return builder.build();
To deserialize you need to extend }
io.quarkus.kafka.client.serialization.JsonbDeserializer and MQTT con guration schema: mp.messaging.[outgoing|incoming]. }
provide a type. {stream-name}.<property>=<value> .

public class BeerDeserializer


The connector type is smallrye-mqtt .
Previous example produces content to another stream. If you want
extends JsonbDeserializer<Beer> { to write interactive queries, you can use Kafka streams.
mp.messaging.outgoing.topic-price.type=
public BeerDeserializer() { smallrye-mqtt
mp.messaging.outgoing.topic-price.topic= @Inject
super(Beer.class);
prices KafkaStreams streams;
}
mp.messaging.outgoing.topic-price.host=

localhost return streams
}
mp.messaging.outgoing.topic-price.port= .store("stream", QueryableStoreTypes.keyValueStore
1883 ());
mp.messaging.outgoing.topic-price.auto-generated-client-id=
AMQP
true

To integrate with AMQP you need to add next extensions:


The Kafka Streams extension is con gured via the Quarkus
mp.messaging.incoming.prices.type= con guration le application.properties .
smallrye-mqtt
./mvnw quarkus:add-extension mp.messaging.incoming.prices.topic=
-Dextensions="reactive-messaging-amqp" quarkus.kafka-streams.bootstrap-servers=localhost:9092
prices
quarkus.kafka-streams.application-id=temperature-aggregator
mp.messaging.incoming.prices.host=
quarkus.kafka-streams.application-server=${hostname}:8080
localhost
quarkus.kafka-streams.topics=weather-stations,temperature-v
Then @Outgoing , @Incoming or @Stream can be used. mp.messaging.incoming.prices.port=
alues
1883

AMQP con guration schema: mp.messaging.[outgoing|incoming]. mp.messaging.incoming.prices.auto-generated-client-id=
kafka-streams.cache.max.bytes.buffering=10240
{stream-name}.<property>=<value> . Special properties amqp-username true
kafka-streams.commit.interval.ms=1000
and amqp-password are used to con gure AMQP broker credentials.

The connector type is smallrye-amqp .


Kafka Streams IMPORTANT: All the properties within the kafka-streams
amqp-username=quarkus namespace are passed through as-is to the Kafka Streams engine.
amqp-password=quarkus Create streaming queries with the Kafka Streams API. Changing their values requires a rebuild of the application.
# write
mp.messaging.outgoing.generated-price.connector= ./mvnw quarkus:add-extension Reactive PostgreSQL Client
smallrye-amqp -Dextensions="kafka-streams"
mp.messaging.outgoing.generated-price.address= You can use Reactive PostgreSQL to execute queries to PostreSQL
prices database in a reactive way, instead of using JDBC way.
mp.messaging.outgoing.generated-price.durable=
All we need to do for that is to declare a CDI producer method
true
which returns the Kafka Streams ./mvnw quarkus:add-extension
# read
org.apache.kafka.streams.Topology : -Dextensions="quarkus-reactive-pg-client"
mp.messaging.incoming.prices.connector=
smallrye-amqp
mp.messaging.incoming.prices.durable=
true Database con guration is the same as shown in Persistence
section, but URL is different as it is not a jdbc.

A complete list of supported properties for AMQP.


quarkus.datasource.url= @ApplicationScoped
And then you can inject
vertx-reactive:postgresql://host:5431/db public class ArtemisConsumerManager {
org.apache.activemq.artemis.api.core.client.ServerLocator

instance.
@Inject
ConnectionFactory connectionFactory;
Then you can inject io.vertx.axle.pgclient.PgPool class. @ApplicationScoped
public class ArtemisConsumerManager { private Connection connection;
@Inject
PgPool client; @Inject @PostConstruct
ServerLocator serverLocator; public void init() throws JMSException {
CompletionStage<JsonArray> = connection = connectionFactory.createConnection();
client.query("SELECT * FROM table") private ClientSessionFactory connection; connection.start();
.thenApply(rowSet -> { }
JsonArray jsonArray = new JsonArray(); @PostConstruct }
PgIterator iterator = rowSet.iterator(); public void init() throws Exception {
return jsonArray; connection = serverLocator.createSessionFactory();
}) }
} INFO: Con guration options are the same as Artemis core.

Reactive MySQL Client


And con gure ServerLocator in application.properties :
You can use Reactive MySQL to execute queries to MySQL
database in a reactive way, instead of using JDBC way. quarkus.artemis.url=tcp://localhost:61616

./mvnw quarkus:add-extension
-Dextensions="quarkus-reactive-mysql-client" You can con gure ActiveMQ Artemis in application.properties le
by using next properties pre xed with quarkus :

Database con guration is the same as shown in Persistence Parameter Default Description
section, but URL is different as it is not a jdbc.
artemis.url Connection URL
quarkus.datasource.url=
vertx-reactive:mysql://localhost:3306/db Username for
artemis.username
authentication.

Then you can inject io.vertx.axle.mysqlclient.MySQLPool class.


Password for
artemis.password
authentication.
@Inject
MySQLPool client;

Artemis JMS
public static CompletionStage<Fruit> findById(
MySQLPool c, Long id) { If you want to use JMS with Artemis, you can do it by using its
return c.preparedQuery("SELECT name FROM fruits WHERE i extension:
d = $1",
Tuple.of(id))
./mvnw quarkus:add-extension
.thenApply(RowSet::iterator)
-Dextensions="quarkus-artemis-jms"
.thenApply(iterator -> iterator.hasNext() ?
from(iterator.next()) : null);
}
And then you can inject javax.jms.ConnectionFactory :

ActiveMQ Artemis
Quarkus uses Reactive Messaging to integrate with messaging
systems, but in case you need deeper control when using Apache
ActiveMQ Artemis there is also an extension:

./mvnw quarkus:add-extension
-Dextensions="quarkus-artemis-core"
RBAC You need to provide permissions set by using the roles-allowed
Parameter Default Description

property or use the built-in ones deny , permit or authenticated . Public Key text
You can set RBAC using annotations or in application.properties .
itself to be
JWT mp.jwt.verify.publickey none
Annotations supplied as a
string.
You can de ne roles by using Quarkus implements MicroPro le JWT RBAC spec.
javax.annotation.security.RolesAllowed annotation.

mvn quarkus:add-extension Relative path or


@RolesAllowed("Subscriber") -Dextensions="io.quarkus:quarkus-smallrye-jwt" mp.jwt.verify.publickey.location none URL of a public
key.

You can use io.quarkus.security.Authenticated as a shortcut of Minimum JWT required claims: typ , alg , kid , iss , sub , exp , iat , iss accepted as
@RolesAllowed("*") . jti , upn , groups .
mp.jwt.verify.issuer none
valid.
To alter RBAC behaviour there are two con guration properties: You can inject token by using JsonWebToken or a claim individually by
using @Claim . Supported public key formats:
quarkus.security.deny-unannotated=true
@Inject PKCS#8 PEM
JsonWebToken jwt;

JWK
Con guration options:
@Inject
JWKS
@Claim(standard = Claims.preferred_username)
Parameter Default Description
String name; JWK Base64 URL

If true denies by
quarkus.jaxrs.deny- @Inject JWKS Base64 URL
false default to all JAX-RS
uncovered @Claim("groups")
endpoints.
Set<String> groups; To send a token to server-side you should use Authorization
header: curl -H "Authorization: Bearer eyJraWQiOi… " .
If true denies by
To inject claim values, the bean must be @RequestScoped CDI
quarkus.security.deny- default all CDI Set of supported types: String , Set<String> , Long , Boolean,
false
methods and JAX-RS scoped. If you need to inject claim values in scope with a lifetime
unannotated `javax.json.JsonValue , Optional ,
greater than @RequestScoped then you need to use
endpoints. org.eclipse.microprofile.jwt.ClaimValue .
javax.enterprise.inject.Instance interface.

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


File Con guration @Inject
@Claim(standard = Claims.iat)
mp.jwt.verify.publickey.location=
De ning RBAC in application.properties instead of using private Instance<Long> providerIAT;
META-INF/resources/publicKey.pem
annotations.
mp.jwt.verify.issuer=
https://quarkus.io/using-jwt-rbac
quarkus.http.auth.policy.role-policy1.roles-allowed= RBAC
user,admin
quarkus.http.auth.permission.roles1.paths= JWT groups claim is directly mapped to roles to be used in security
Con guration options:
/roles-secured/*,/other/*,/api/* annotations.
quarkus.http.auth.permission.roles1.policy=
role-policy1
Parameter Default Description
@RolesAllowed("Subscriber")

quarkus.http.auth.permission.permit1.paths= Determine if the
/public/* quarkus.smallrye-jwt.enabled true jwt extension is
enabled.
quarkus.http.auth.permission.permit1.policy= OpenId Connect
permit
quarkus.http.auth.permission.permit1.methods= Quarkus can use OpenId Connect or OAuth 2.0 authorization
Name to use for
GET quarkus.smallrye-jwt.realm-name Quarkus-JWT servers such as Keycloak to protect resources using bearer token
security realm.
issued by Keycloak server.
quarkus.http.auth.permission.deny1.paths=
/forbidden
quarkus.smallrye-jwt.auth- Authentication mvn quarkus:add-extension
quarkus.http.auth.permission.deny1.policy= MP-JWT
mechanism mechanism. -Dextensions="using-openid-connect"
deny

You can also protect resources with security annotations.


@GET mvn quarkus:add-extension
And con guration in src/main/resources/application.properties :
@RolesAllowed("admin") -Dextensions="elytron-security-properties-file"

quarkus.oauth2.client-id=client_id
quarkus.oauth2.client-secret=secret
Con gure application to Keycloak service in application.properties quarkus.oauth2.introspection-url=http://oauth-server/intros You need to con gure the extension with users and roles les:
le. pect
And con guration in src/main/resources/application.properties :
quarkus.oidc.realm=quarkus
quarkus.oidc.auth-server-url=http://localhost:8180/auth quarkus.security.users.file.enabled=true
And you can map roles to be used in security annotations. quarkus.security.users.file.users=test-users.properties
quarkus.oidc.resource=backend-service
quarkus.oidc.bearer-only=true quarkus.security.users.file.roles=test-roles.properties
quarkus.oidc.credentials.secret=secret @RolesAllowed("Subscriber") quarkus.security.users.file.auth-mechanism=BASIC
quarkus.security.users.file.realm-name=MyRealm
quarkus.security.users.file.plain-text=true

Con guration options with quarkus.oidc pre x: Con guration options:

Parameter Default Description Parameter Default Description Then users.properties and roles.properties :

The base URL of the Determine if the scott=jb0ss


auth-server-url OpenID Connect quarkus.oauth2.enabled true OAuth2 extension jdoe=p4ssw0rd
(OIDC) server is enabled.

Relative path of the The OAuth2 client scott=Admin,admin,Tester,user


introspection-path RFC7662 quarkus.oauth2.client-id id used to validate jdoe=NoRolesUser
introspection service the token.

The OAuth2 client IMPORTANT: If plain-text is set to false (or omitted) then
Relative path of the
quarkus.oauth2.client-secret secret used to passwords must be stored in the form MD5
jwks-path OIDC service
validate the token. ( username :`realm`:`password`).
returning a JWK set
Elytron File Properties con guration properties. Pre x
URL used to quarkus.security.users is skipped.
Public key for the
public-key local JWT token validate the token
quarkus.oauth2.introspection- Parameter Default Description
veri cation and gather the
url
authentication
claims. The le realm is
file.enabled false
The client-id of the enabled
client-id
application.
The claim that is
used in the The authentication
quarkus.oauth2.role-claim scope file.auth-mechanism BASIC
credentials.secret The client secret endpoint response mechanism
to load the roles
With Keycloak OIDC server The authentication
https://host:port/auth/realms/{realm} where {realm} has file.realm-name Quarkus
realm name
to be replaced by the name of the Keycloak realm. Authenticating via HTTP
You can use quarkus.http.cors property to enable
consuming form different domain. HTTP basic auth is enabled by the quarkus.http.auth.basic=true
If passwords are in
property. file.plain-text false
plain or in MD5
OAuth2 HTTP form auth is enabled by the
quarkus.http.auth.form.enabled=true property.
Classpath resource
Quarkus integrates with OAuth2 to be used in case of opaque file.users users.properties
of user/password
tokens (none JWT) and its validation against an introspection Then you need to add elytron-security-properties-file or elytron-
endpoint. security-jdbc .

Classpath resource
mvn quarkus:add-extension Security with Properties File file.roles roles.properties
of user/role
-Dextensions="security-oauth2"
You can also protect endpoints and store identities (user, roles) in
the le system. Embedded Realm
You can embed user/password/role in the same Parameter Default Description
quarkus.datasource.url=
application.properties :
quarkus.datasource.driver=org.h2.Driver
quarkus.datasource.username=sa principal-
The index of column
quarkus.security.users.embedded.enabled=true quarkus.datasource.password=sa query.bcrypt-
0 containing password
quarkus.security.users.embedded.plain-text=true password-
hash
quarkus.security.users.embedded.users.scott=jb0ss quarkus.security.jdbc.enabled=true mapper.password-index
quarkus.security.users.embedded.roles.scott=admin,tester,us quarkus.security.jdbc.principal-query.sql=
er SELECT u.password, u.role FROM test_user u WHERE u.user
quarkus.security.users.embedded.auth-mechanism=BASIC =? principal- A string referencing
quarkus.security.jdbc.principal-query query.bcrypt- the password hash
BASE64
.clear-password-mapper.enabled=true password-mapper.hash- encoding ( BASE64 or
quarkus.security.jdbc.principal-query encoding HEX )
IMPORTANT: If plain-text is set to false (or omitted) then
passwords must be stored in the form MD5 .clear-password-mapper.password-index=1
( username :`realm`:`password`). quarkus.security.jdbc.principal-query
principal-
.attribute-mappings.0.index=2 The index column
query.bcrypt-
Pre x quarkus.security.users.embedded is skipped. quarkus.security.jdbc.principal-query 0 containing the Bcrypt
password-mapper.salt-
.attribute-mappings.0.to=groups salt
index
Parameter Default Description

The le realm is You need to set the index (1-based) of password and role. principal-
file.enabled false
enabled A string referencing
query.bcrypt-
Elytron JDBC Realm con guration properties. Pre x BASE64 the salt encoding
password-mapper.salt-
quarkus.security.jdbc is skipped. ( BASE64 or HEX )
encoding
The authentication
file.auth-mechanism BASIC
mechanism Parameter Default Description
principal-
The authentication query.bcrypt- The index column
The authentication auth-mechanism BASIC
mechanism
file.realm-name Quarkus password- 0 containing the Bcrypt
realm name
mapper.iteration- iteration count
count-index
The authentication
If passwords are in realm-name Quarkus
realm name
file.plain-text false
plain or in MD5 For multiple datasources you can use the datasource name in the
properties:
If the properties store
* is user and value is enabled false
file.users.* is enabled quarkus.datasource.url=
password
quarkus.security.jdbc.principal-query.sql=

The sql query to nd
* is user and value is principal-query.sql quarkus.datasource.permissions.url=
file.roles.* the password
role quarkus.security.jdbc.principal-query.permissions.sql=

principal- The data source to


Security with a JDBC Realm query.datasource use Vault
You can also protect endpoints and store identities in a database. Quarkus integrates with Vault to manage secrets or protecting
principal-
If the clear-password- sensitive data.
query.clear-password- false
mvn quarkus:add-extension mapper is enabled
mapper.enabled
-Dextensions="elytron-security-jdbc"
mvn quarkus:add-extension
-Dextensions="vault"
principal- The index of column
You still need to add the database driver (ie jdbc-h2 ). query.clear-password- 1 containing clear
mapper.password-index password And con guring Vault in application.properties :
You need to con gure JDBC and Elytron JDBC Realm:

principal-
If the bcrypt-
query.bcrypt-
false password-mapper is
password-
enabled
mapper.enabled
# vault url Parameter Default Description Parameter Default Description
quarkus.vault.url=http://localhost:8200
Vault token to Certi cate bundle
authentication.client-token
quarkus.vault.authentication.userpass.username= access used to validate
tls.ca-cert
bob TLS
quarkus.vault.authentication.userpass.password= communications
sinclair Role Id for
authentication.app-role.role-id
AppRole auth
# path within the kv secret engine tls.use-kubernetes-ca-cert true TLS will be active
quarkus.vault.secret-config-kv-path=
authentication.app-role.secret- Secret Id for
myapps/vault-quickstart/config
id AppRole auth Tiemout to
connect-timeout 5S establish a
connection
Then you can inject the value con gured at secret/myapps/vault- Username for
authentication.userpass.username
quickstart/a-private-key . userpass auth
read-timeout 1S Request timeout
@ConfigProperty(name = "a-private-key")
String privateKey; Password for
authentication.userpass.password
userpass auth credentials-
provider."credentials- Database
provider".database-credentials- credentials role
You can access the KV engine programmatically: Kubernetes role
authentication.kubernetes.role
authentication role
@Inject
VaultKVSecretEngine kvSecretEngine; credentials- A path in vault kv
Location of the le provider."credentials- store, where we
kvSecretEngine.readSecret("myapps/vault-quickstart/" + vaul authentication.kubernetes.jwt- containing the provider".kv-path will nd the kv-key
tPath).toString(); token-path Kubernetes JWT
token
credentials- Key name to
provider."credentials- password search in vault
Fetching credentials DB Renew grace provider".kv-key path kv-path
renew-grace-period 1H
period duration.
With the next kv vault kv put secret/myapps/vault-quickstart/db
password=connor

Vault con g
quarkus.vault.credentials-provider.mydatabase.kv-path= secret-config-cache-period 10M source cache
myapps/vault-quickstart/db period
quarkus.datasource.credentials-provider=
mydatabase
Vault path in kv
secret-config-kv-path
quarkus.datasource.url= store
jdbc:postgresql://localhost:5432/mydatabase
quarkus.datasource.driver=
org.postgresql.Driver Used to hide
quarkus.datasource.username= log-confidentiality-level medium con dential infos.
sarah low , medium , high

Kv secret engine
No password is set as it is fetched from Vault. kv-secret-engine-version 1
version
INFO: dynamic database credentials through the database-
credentials-role property.
Kv secret engine
kv-secret-engine-mount-path secret
path
Elytron JDBC Realm con guration properties. Pre x quarkus.vault
is skipped.
Allows to bypass
Parameter Default Description
certi cate
tls.skip-verify false
validation on TLS
url Vault server URL
communications
JAX-RS Property Description Example @Provider
public class LoggingFilter
Quarkus uses JAX-RS to de ne REST-ful web APIs. Under the Gets cookie implements ContainerRequestFilter {
covers, Rest-EASY is working with Vert.X directly without using any @CookieParam param by
Servlet. name. @Context
UriInfo info;
It is important to know that if you want to use any feature that
implies a Servlet (ie Servlet Filters) then you need to add the Gets header @Context
quarkus-undertow extension to switch back to the Servlet @HeaderParam parameter by HttpServletRequest request;
ecosystem but generally speaking, you don’t need to add it as name.
everything else is well-supported. @Override
public void filter(ContainerRequestContext context) {
Valid HTTP method annotations provided by the spec are: @GET ,
@Path("/book") final String method = context.getMethod();
@POST , @PUT , @DELETE , @PATCH , @HEAD and @OPTIONS .
public class BookResource { final String path = info.getPath();
final String address = request.getRemoteAddr();
You can create new annotations that bind to HTTP methods not
@GET System.out.println("Request %s %s from IP %s",
de ned by the spec.
@Produces(MediaType.APPLICATION_JSON) method, path, address);
public List<Book> getAllBooks() {} }
@Target({ElementType.METHOD})

@Retention(RetentionPolicy.RUNTIME) }
@POST
@HttpMethod("LOCK")
@Produces(MediaType.APPLICATION_JSON)
public @interface LOCK {
public Response createBook(Book book) {}
}
Exception Mapper

@DELETE
@LOCK
@Path("{isbn}")
public void lockIt() {}
You can map exceptions to produce a custom output by
@Produces(MediaType.APPLICATION_JSON)
}
implementing ExceptionMapper interface:
public Response deleteBook(
@PathParam("isbn") String isbn) {}
@Provider

public class ErrorMapper
Injecting
implements ExceptionMapper<Exception> {
@GET

@Produces(MediaType.APPLICATION_JSON) Using @Context annotation to inject JAX-RS and Servlet information.
@Override
@Path("search")
public Response toResponse(Exception exception) {
public Response searchBook( @GET int code = 500;
@QueryParam("description") String description) {} public String getBase(@Context UriInfo uriInfo) { if (exception instanceof WebApplicationException) {
} return uriInfo.getBaseUri(); code = ((WebApplicationException) exception)
} .getResponse().getStatus();
}
To get information from request: return Response.status(code)
Possible injectable objects: SecurityContext , Request , Application , .entity(
Property Description Example Configuration , Providers , ResourceContext , ServletConfig , Json.createObjectBuilder()
ServletContext , HttpServletRequest , HttpServletResponse , .add("error", exception.getMessage())
Gets content HttpHeaders , Urinfo , SseEventSink and Sse . .add("code", code)
@PathParam from request /book/{id} @PathParam("id") .build()
URI. HTTP Filters )
.build();
HTTP request and response can be intercepted to manipulate the }
Gets query metadata (ie headers, parameters, media type, … ) or abort a }
@QueryParam /book?desc="" @QueryParam("desc)
parameter. request. You only need to implement the next
ContainerRequestFilter and ContainerResponseFilter JAX-RS
interfaces respectively.
@FormParam
Gets form Vert.X Filters and Routes
parameter.
Programmatically

Get URI You can also register Vert.X Filters and Router programmatically
@MatrixParam matrix /book;author=mkyong;country=malaysia inside a CDI bean:
parameter.
import io.quarkus.vertx.http.runtime.filters.Filters;
You can con gure Quarkus to use GZip in the @Path("/api")
application.properties le using the next properties with
import io.vertx.ext.web.Router; @RegisterRestClient
quarkus.resteasy su x:
import javax.enterprise.context.ApplicationScoped; public interface WorldClockService {
import javax.enterprise.event.Observes; @GET @Path("/json/cet/now")
Parameter Default Description
@Produces(MediaType.APPLICATION_JSON)
@ApplicationScoped @Retry(maxRetries = 2)
public class MyBean {
gzip.enabled false EnableGZip. WorldClock getNow();
}
public void filters(
Con gure the upper
@Observes Filters filters) {
gzip.max-input 10M limit on de ated
filters
request body. You can set fallback code in case of an error by using @Fallback
.register(
annotation:
rc -> {
rc.response()
.putHeader("X-Filter", "filter 1"); CORS Filter @Retry(maxRetries = 1)
rc.next(); @Fallback(fallbackMethod = "fallbackMethod")
}, Quarkus comes with a CORS lter that can be enabled via WorldClock getNow(){}
10); con guration:
} public WorldClock fallbackMethod() {
return new WorldClock();
quarkus.http.cors=true
public void routes( }
@Observes Router router) {
router
Pre x is quarkus.http .
.get("/") fallbackMethod must have the same parameters and return type as
.handler(rc -> rc.response().end("OK"));
Property Default Description the annotated method.
}
} You can also set logic into a class that implements FallbackHandler
cors false Enable CORS.
interface:

Declarative CSV of origins public class RecoverFallback


cors.origins Any request valid.
allowed. implements FallbackHandler<WorldClock> {
You can use @Route annotation to use reactive routes and @Override
@RouteFilter to sue reactive lters in a declarative way: public WorldClock handle(ExecutionContext context) {
CSV of methods }
cors.methods Any method valid.
./mvnw quarkus:add-extension valid. }
-Dextensions="quarkus-vertx-web"

Any requested header CSV of valid allowed


cors.headers And set it in the annotation as value
valid. headers. @Fallback(RecoverFallback.class) .
@ApplicationScoped
public class MyDeclarativeRoutes { In case you want to use circuit breaker pattern:
CSV of valid exposed
cors.exposed-headers
@Route(path = "/hello", methods = HttpMethod.GET) headers.
@CircuitBreaker(requestVolumeThreshold = 4,
public void greetings(RoutingContext rc) {
failureRatio=0.75,
String name = rc.request().getParam("name");
delay = 1000)
if (name == null) { Fault Tolerance WorldClock getNow(){}
name = "world";
} Quarkus uses MicroPro le Fault Tolerance spec:
rc.response().end("hello " + name);
} If 3 (4 x 0.75) failures occur among the rolling window of 4
./mvnw quarkus:add-extension
consecutive invocations then the circuit is opened for 1000 ms and
-Dextensions="io.quarkus:quarkus-smallrye-fault-toleranc
@RouteFilter(20) then be back to half open. If the invocation succeeds then the
e"
void filter(RoutingContext rc) { circuit is back to closed again.
rc.response().putHeader("X-Filter", "filter 2");
rc.next(); You can use bulkahead pattern to limit the number of concurrent
} MicroPro le Fault Tolerance spec uses CDI interceptor and it can access to the same resource. If the operation is synchronous it
be used in several elements such as CDI bean, JAX-RS resource or uses a semaphore approach, if it is asynchronous a thread-pool
} MicroPro le Rest Client. one. When a request cannot be processed BulkheadException is
thrown. It can be used together with any other fault tolerance
To do automatic retries on a method: annotation.

GZip Support
Quarkus relies on MicroPro le Health spec to provide health
@Bulkhead(5) @ApplicationScoped
checks.
@Retry(maxRetries = 4, public class DatabaseHealthCheck {
delay = 1000,
retryOn = BulkheadException.class) ./mvnw quarkus:add-extension @Produces
WorldClock getNow(){} -Dextensions="io.quarkus:quarkus-smallrye-health" @Liveness
HealthCheck check1() {
return io.smallrye.health.HealthStatus
By just adding this extension, an endpoint is registered to /health .up("successful-live");
Fault tolerance annotations:
providing a default health check. }

Annotation Properties
@Produces
{
@Readiness
@Timeout unit "status": "UP",
HealthCheck check2() {
"checks": [
return HealthStatus
]
.state("successful-read", this::isReady)
maxRetries , delay , delayUnit , }
}
maxDuration , durationUnit ,
@Retry
jitter , jitterDelayUnit , retryOn ,
private boolean isReady() {}
abortOn
To create a custom health check you need to implement the }
HealthCheck interface and annotate either with @Readiness (ready to

@Fallback fallbackMethod
process requests) or @Liveness (is running) annotations.
You can ping liveness or readiness health checks individually by
@Readiness querying /health/live or /health/ready .
waitingTaskQueue (only valid in public class DatabaseHealthCheck implements HealthCheck {
@Bulkhead
asynchronous) @Override Quarkus comes with some HealthCheck implementations for
public HealthCheckResponse call() { checking service status.
HealthCheckResponseBuilder responseBuilder =
failOn , delay , delayUnit , HealthCheckResponse.named("Database conn"); SocketHealthCheck: checks if host is reachable using a
@CircuitBreaker requestVolumeThreshold , socket.
failureRatio , successThreshold try {
checkDatabaseConnection(); UrlHealthCheck: checks if host is reachable using a Http URL
responseBuilder.withData("connection", true); connection.
@Asynchronous responseBuilder.up();
} catch (IOException e) {
InetAddressHealthCheck: checks if host is reachable using
InetAddress.isReachable method.
// cannot access the database
You can override annotation parameters via con guration le using responseBuilder.down()
property [classname/methodname/]annotation/parameter : .withData("error", e.getMessage()); @Produces
} @Liveness
org.acme.quickstart.WorldClock/getNow/Retry/maxDuration=30 return responseBuilder.build(); HealthCheck check1() {
# Class scope } return new UrlHealthCheck("https://www.google.com")
org.acme.quickstart.WorldClock/Retry/maxDuration=3000 } .name("Google-Check");
# Global }
Retry/maxDuration=3000

Builds the next output:


If you want to override or set manually readiness/liveness probes,
You can also enable/disable policies using special parameter {
you can do it by setting health properties:
enabled .
"status": "UP",
"checks": [ quarkus.smallrye-health.root-path=/hello
org.acme.quickstart.WorldClock/getNow/Retry/enabled=false { quarkus.smallrye-health.liveness-path=/customlive
# Disable everything except fallback "name": "Database conn", quarkus.smallrye-health.readiness-path=/customready
MP_Fault_Tolerance_NonFallback_Enabled=false "status": "UP",
"data": {
"connection": true Automatic readiness probes
}
MicroPro le Fault Tolerance integrates with MicroPro le
Metrics spec. You can disable it by setting
} Some default readiness probes are provided by default if any of the
MP_Fault_Tolerance_Metrics_Enabled to false.
] next features are added:
}
datasource
Observability A probe to check database connection status.
Health Checks Since health checks are CDI beans, you can do:
kafka
A probe to check kafka connection status. In this case you need Annotation Description @Inject
to enable manually by setting quarkus.kafka.health.enabled to
Tracer tracer;
true . Used to inject a metric. Valid
types Meter , Timer , Counter , tracer.activeSpan().setBaggageItem("key", "value");
@Metric
mongoDB Histogram . Gauge only on
A probe to check MongoDB connection status. producer methods/ elds.
You can disable Jaeger extension by using quarkus.jaeger.enabled
neo4j
property.
@GET
A probe to check Neo4J connection status.
//...
Additional tracers
@Timed(name = "checksTimer",
artemis
description = "A measure of how long it takes JDBC Tracer
A probe to check Artemis JMS connection status. to perform a hello.",
unit = MetricUnits.MILLISECONDS) Adds a span for each JDBC queries.
kafka-streams public String hello() {}
Liveness (for stream state) and Readiness (topics created)
<dependency>
probes. @Counted(name = "countWelcome",
<groupId>io.opentracing.contrib</groupId>
description = "How many welcome have been performed.")
<artifactId>opentracing-jdbc</artifactId>
You can disable the automatic generation by setting public String hello() {}
</dependency>
<component>.health.enabled to false.

quarkus.kafka-streams.health.enabled=false @Gauge annotation returning a measure as a gauge.


Con gure JDBC driver apart from tracing properties seen before:
quarkus.mongodb.health.enabled=false
quarkus.neo4j.health.enabled=false @Gauge(name = "hottestSauce", unit = MetricUnits.NONE,
# add ':tracing' to your database URL
description = "Hottest Sauce so far.")
quarkus.datasource.url=
public Long hottestSauce() {}
jdbc:tracing:postgresql://localhost:5432/mydatabase
Metrics quarkus.datasource.driver=
io.opentracing.contrib.jdbc.TracingDriver
Quarkus can utilize the MicroPro le Metrics spec to provide metrics
Injecting a histogram using @Metric . quarkus.hibernate-orm.dialect=
support. org.hibernate.dialect.PostgreSQLDialect
@Inject
./mvnw quarkus:add-extension
@Metric(name = "histogram")
-Dextensions="io.quarkus:quarkus-smallrye-metrics"
Histogram historgram;

The metrics can be read with JSON or the OpenMetrics format. An


Tracing
endpoint is registered automatically at /metrics providing default
metrics. Quarkus can utilize the MicroPro le OpenTracing spec.
MicroPro le Metrics annotations:
./mvnw quarkus:add-extension
Annotation Description -Dextensions="io.quarkus:quarkus-smallrye-opentracing"

@Timed Tracks the duration.


Requests sent to any endpoint are traced automatically.

Tracks the frequency of This extension includes OpenTracing support and Jaeger tracer.
@Metered
invocations.
Jaeger tracer con guration:

@Counted Counts number of invocations. quarkus.jaeger.service-name=myservice


quarkus.jaeger.sampler-type=const
quarkus.jaeger.sampler-param=1
Samples the value of the quarkus.jaeger.endpoint=http://localhost:14268/api/traces
@Gauge
annotated object.

Gauge to count parallel @Traced annotation can be set to disable tracing at class or method
@ConcurrentGauge
invocations. level.

Tracer class can be injected into the class.


Cloud All possible values are explained at Property Default Description
https://quarkus.io/guides/kubernetes#con guration-options.
Native watch-reconnect- Watch reconnect
Kubernetes Deployment Targets interval
PT1S
interval.
You can build a native image by using GraalVM. The common use
You can generate different resources setting the property
case is creating a Docker image so you can execute the next
kubernetes.deployment.target .
commands: watch-reconnect- Maximum reconnect
-1
limit attempts.
Possible values are kubernetes , openshift and knative . The default
./mvnw package -Pnative -Dquarkus.native.container-build=tr value is kubernetes .
ue
Maximum amount of
Kubernetes Client connection-timeout PT10S time to wait for a
docker build -f src/main/docker/Dockerfile.native
connection.
-t quarkus/getting-started . Quarkus integrates with Fabric8 Kubernetes Client.
docker run -i --rm -p 8080:8080 quarkus/getting-started

./mvnw quarkus:add-extension Maximum amount of


-Dextensions="quarkus-kubernetes-client" request-timeout PT10S time to wait for a
You can use quarkus.native.container-runtime to select the request.
container runtime to use. Now docker (default) and podman are the
valid options.
List of Kubernetes client parameters. Maximum amount of
rolling-timeout PT15M time to wait for a
./mvnw package -Pnative -Dquarkus.native.container-runtime= quarkus.kubernetes-client as pre x is skipped in the next table.
podman
rollout.
Property Default Description
HTTP proxy used to
To con gure native application, you can create a config directory at Trust self-signed http-proxy access the
trust-certs false
the same place as the native le and place an certi cates. Kubernetes.
application.properties le inside. config/application.properties .

Kubernetes URL of Kubernetes HTTPS proxy used to


master-url
API server. https-proxy `` access the
Quarks can use Dekorate to generate Kubernetes resources. Kubernetes.

./mvnw quarkus:add-extensions
namesapce Default namespace.
-Dextensions="io.quarkus:quarkus-kubernetes" proxy-username Proxy username.
ca-cert-file CA certi cate data.
proxy-password Proxy password.
Running ./mvnw package the Kubernetes resources are created at
target/kubernetes/ directory. client-cert-file Client certi cate le.
IP addresses or hosts
Property Default Description no-proxy to exclude from
Client certi cate proxying
client-cert-data
Set Docker data.
kubernetes.group Current username
Username.
Or programmatically:
client-key-data Client key data.
Current project
quarkus.application.name Project name @Dependent
name
client-key-algorithm Client key algorithm. public class KubernetesClientProducer {

@Produces
Generated resource is integrated with MicroPro le Health
annotations. client-key- Client key public KubernetesClient kubernetesClient() {
passphrase passphrase. Config config = new ConfigBuilder()
Also, you can customize the generated resource by setting the new .withMasterUrl("https://mymaster.com")
values in application.properties : .build();
username Username. return new DefaultKubernetesClient(config);
}
kubernetes.replicas=3
}

password Password.
kubernetes.labels[0].key=foo
kubernetes.labels[0].value=bar
And inject it on code:
kubernetes.readiness-probe.period-seconds=45
@Inject ./mvnw quarkus:add-extension mvn archetype:generate \
KubernetesClient client; -Dextensions="io.quarkus:quarkus-amazon-lambda" -DarchetypeGroupId=io.quarkus \
-DarchetypeArtifactId=quarkus-azure-functions-http-archet
ServiceList myServices = client.services().list(); ype \
-DarchetypeVersion={version}
And then implement
Service myservice = client.services()
com.amazonaws.services.lambda.runtime.RequestHandler interface.
.inNamespace("default")
.withName("myservice")
.get(); public class TestLambda
implements RequestHandler<MyInput, MyOutput> {
CustomResourceDefinitionList crds = client @Override
.customResourceDefinitions() public MyInput handleRequest(MyOutput input,
.list(); Context context) {
}
dummyCRD = new CustomResourceDefinitionBuilder() }
...
.build()
client.customResourceDefinitions() You can set the handler name by using quarkus.lambda.handler
.create(dummyCRD); property or by annotating the Lambda with the CDI @Named
annotation.

Test
Testing
You can write tests for Amazon lambdas:
Quarkus provides a Kubernetes Mock test resource that starts a
mock of Kubernetes API server and sets the proper environment
variables needed by Kubernetes Client. <dependency>
<groupId>io.quarkus</groupId>
Register next dependency: io.quarkus:quarkus-test-kubernetes- <artifactId>quarkus-test-amazon-lambda</artifactId>
client:test . <scope>test</scope>
</dependency>
@QuarkusTestResource(KubernetesMockServerTestResource.clas
s)
@QuarkusTest
@Test
public class KubernetesClientTest {
public void testLambda() {

MyInput in = new MyInput();
@MockServer
in.setGreeting("Hello");
private KubernetesMockServer mockServer;
in.setName("Stu");

MyOutput out = LambdaClient.invoke(MyOutput.class, in);
@Test
}
public void test() {
final Pod pod1 = ...
mockServer
.expect() To scaffold a AWS Lambda run:
.get()
.withPath("/api/v1/namespaces/test/pods") mvn archetype:generate \
.andReturn(200, -DarchetypeGroupId=io.quarkus \
new PodListBuilder() -DarchetypeArtifactId=quarkus-amazon-lambda-archetype \
.withNewMetadata() -DarchetypeVersion={version}
.withResourceVersion("1")
.endMetadata()
.withItems(pod1, pod2)
.build()) Azure Functions
.always();
} Quarkus can make a microservice be deployable to the Azure
} Functions.

To scaffold a deployable microservice to the Azure Functions run:

Amazon Lambda
Quarkus integrates with Amazon Lambda.
Apache Camel You can customize the output by using Open API v3 annotations.
mailer.send(
Mail.withText("to@acme.org", "Subject", "Body")
Apache Camel Quarkus has its own site: @Schema(name="Developers", );
https://github.com/apache/camel-quarkus description="POJO that represents a developer.")
public class Developer { CompletionStage<Void> stage =
WebSockets @Schema(required = true, example = "Alex") reactiveMailer.send(
private String name; Mail.withText("to@acme.org", "Subject", "Body")
} );
Quarkus can be used to handling web sockets.

@POST
./mvnw quarkus:add-extension
@Path("/developer")
-Dextensions="io.quarkus:quarkus-undertow-websockets" Mail class contains methods to add cc , bcc , headers , bounce
@Operation(summary = "Create deeloper",
address , reply to , attachments , inline attachments and html body .
description = "Only be done by admin.")
public Response createDeveloper(
And web sockets classes can be used: @RequestBody(description = "Developer object", mailer.send(Mail.withHtml("to@acme.org", "Subject", body)
required = true, .addInlineAttachment("quarkus.png",
content = @Content(schema = new File("quarkus.png"),
@ServerEndpoint("/chat/{username}")
@Schema(implementation = Developer.class))) "image/png", "<my-image@quarkus.io>"));
@ApplicationScoped
public class ChatSocket { Developer developer)

@OnOpen If you need deep control you can inject Vert.x mail client
public void onOpen(Session session, All possible annotations can be seen at @Inject MailClient client;
@PathParam("username") String username) {} org.eclipse.micropro le.openapi.annotations package.
You need to con gure SMTP properties to be able to send an email:
@OnClose You can also serve OpenAPI Schema from static les instead of
public void onClose(..) {} dynamically generated from annotation scanning. quarkus.mailer.from=test@quarkus.io
quarkus.mailer.host=smtp.sendgrid.net
@OnError You need to put OpenAPIdocumentation under META-INF directory
quarkus.mailer.port=465
public void onError(..., Throwable throwable) {} (ie: META-INF/openapi.yaml ).
quarkus.mailer.ssl=true
quarkus.mailer.username=....
@OnMessage A request to /openapi will serve the combined OpenAPI document
from the static le and the generated from annotations. You can quarkus.mailer.password=....
public void onMessage(...) {}
disable the scanning documents by adding the next con guration
} property: mp.openapi.scan.disable=true .
List of Mailer parameters. quarkus. as a pre x is skipped in the next
Other valid document paths are: META-INF/openapi.yml , META- table.
INF/openapi.json , WEB-INF/classes/META-INF/openapi.yml , WEB-
OpenAPI INF/classes/META-INF/openapi.yaml , WEB-INF/classes/META-
INF/openapi.json .

Quarkus can expose its API description as OpenAPI spec and test it
using Swagger UI. Mail Sender

./mvnw quarkus:add-extension You can send emails by using Quarkus Mailer extension:
-Dextensions="io.quarkus:quarkus-smallrye-openapi"
./mvnw quarkus:add-extension
-Dextensions="io.quarkus:quarkus-mailer"

Then you only need to access to /openapi to get OpenAPI v3 spec


of services.
You can inject two possible classes io.quarkus.mailer.Mailer for
You can update the OpenApi path by setting quarkus.smallrye- synchronous API or io.quarkus.mailer.ReactiveMailer for
openapi.path property. asynchronous API.
Also, in case of starting Quarkus application in dev or test mode,
@Inject
Swagger UI is accessible at /swagger-ui . If you want to use it in
Mailer mailer;
production mode you need to set quarkus.swagger-ui.always-

include property to true .
@Inject
You can update the Swagger UI path by setting quarkus.swagger- ReactiveMailer reactiveMailer;
ui.path property.

quarkus.swagger-ui.path=/my-custom-path And then you can use them to send an email:


Parameter Default Description Parameter Default Description Kogito
mailer.from Default address. mailer.key-store- Quarkus integrates with Kogito, a next-generation business
Key store password.
password automation toolkit from Drools and jBPM projects for adding
business automation capabilities.
Emails not sent, just if you enable SSL for the mailer and you want to build a
false in prod , true in
mailer.mock printed and stored in native executable, you will need to enable the SSL support To start using it you only need to add the next extension:
dev and test .
a MockMailbox . quarkus.ssl.native=true .
./mvnw quarkus:add-extension
Testing -Dextensions="kogito"
mailer.bounce-
Default address.
address If quarkus.mailer.mock is set to true , which is the default value in
dev and test mode, you can inject MockMailbox to get the sent
messages. Apache Tika
mailer.host mandatory SMTP host.
@Inject Quarkus integrets with Apache Tika to detect and extract
MockMailbox mailbox; metadata/text from different le types:
mailer.port 25 SMTP port.

@BeforeEach ./mvnw quarkus:add-extension
mailer.username The username. void init() { -Dextensions="quarkus-tika"
mailbox.clear();
}
mailer.password The password.
List<Mail> sent = mailbox @Inject
.getMessagesSentTo("to@acme.org"); io.quarkus.tika.TikaParser parser;
mailer.ssl false Enables SSL.
@POST
@Path("/text")
mailer.trust-all false Trust all certi cates. Scheduled Tasks @Consumes({ "text/plain", "application/pdf",
"application/vnd.oasis.opendocument.text" })
You can schedule periodic tasks with Quarkus. @Produces(MediaType.TEXT_PLAIN)
Max open public String extractText(InputStream stream) {
mailer.max-pool-size 10
connections . @ApplicationScoped return parser.parse(stream).getText();
public class CounterBean { }

Hostname for @Scheduled(every="10s")
mailer.own-host-name HELO/EHLO and void increment() {}
Message-ID
You can con gure Apache Tika in application.properties le by
using next properties pre xed with quarkus :
@Scheduled(cron="0 15 10 * * ?")
void morningTask() {} Parameter Default Description
Connection pool }
mailer.keep-alive true
enabled.
Path to the Tika
tika.tika-config-
tika-config.xml con guration
path
mailer.disable-esmtp false Disable ESMTP. every and cron
parameters can be surrounded with {} and the resource.
value is used as con g property to get the value.

TLS security mode. @Scheduled(cron = "{morning.check.cron.expr}") CSV of the


mailer.start-tls OPTIONAL DISABLED , OPTIONAL , void morningTask() {} abbreviated or full
REQUIRED . quarkus.tika.parsers parser class to be
loaded by the
And con gure the property into application.properties : extension.
Login mode. NONE ,
mailer.login NONE
OPTIONAL , REQUIRED .
morning.check.cron.expr=0 15 10 * * ?
The document may
tika.append-embedded- have other embedded
true
mailer.auth-methods All methods. Space-separated list. content documents. Set if
By default Quarkus expresion is used, but you can change that by autmatically append.
setting quarkus.scheduler.cron-type property.
mailer.key-store Path of the key store.
quarkus.scheduler.cron-type=unix
JGit The implementation of the service sets the locking and what needs
@ApplicationScoped
to be saved/restored:
public class TaskBean {
Quarkus integrets with JGit to integrate with Git repositories:
import org.jboss.stm.annotations.ReadLock; @Transactional
import org.jboss.stm.annotations.State; @Scheduled(every = "10s")
./mvnw quarkus:add-extension
import org.jboss.stm.annotations.WriteLock; void schedule() {
-Dextensions="quarkus-jgit"
Task task = new Task();
public class FlightServiceImpl task.persist();
implements FlightService { }
And then you can start using JGit: @State }
private int numberOfBookings;
try (Git git = Git.cloneRepository()
.setDirectory(tmpDir) @ReadLock
To con gure in clustered mode vida DataSource:
.setURI(url) public int getNumberOfBookings() {
.call()) { return numberOfBookings;
return tmpDir.toString(); } quarkus.datasource.url=jdbc:postgresql://localhost/quarkus_
} test
@WriteLock quarkus.datasource.driver=org.postgresql.Driver
public void makeBooking(String details) { # ...
numberOfBookings += 1;
When running in native mode, make sure to con gure SSL } quarkus.quartz.clustered=true
access correctly quarkus.ssl.native=true (Native and SSL). } quarkus.quartz.store-type=db

Web Resources
Any member is saved/restored automatically ( @State is not You need to de ne the datasource used by clustered mode
You can serve web resources with Quarkus. You need to place web mandatory). You can use @NotState to avoid behaviour. and also import the database tables following the Quartz
resources at src/main/resources/META-INF/resources and then they schema.
are accessible (ie http://localhost:8080/index.html) Transaction boundaries

By default static resources as served under the root context. You Declarative Qute
can change this by using quarkus.http.root-path property.
@NestedTopLevel : De nes that the container will create a new Qute is a templating engine designed speci cally to meet the
top-level transaction for each method invocation. Quarkus needs. Templates should be placed by default at
Transactional Memory src/main/resources/templates aand subdirectories.
@Nested : De nes that the container will create a new top-level
Quarkus integrates with the Software Transactional Memory (STM)
or nested transaction for each method invocation. ./mvnw quarkus:add-extension
implementation provided by the Narayana project.
-Dextensions="quarkus-resteasy-qute"
Programmatically
./mvnw quarkus:add-extension
-Dextensions="narayana-stm" AtomicAction aa = new AtomicAction();
Templates can be de ned in any format, in case of HTML:

aa.begin(); item.html
Transactional objects must be interfaces and annotated with {
org.jboss.stm.annotations.Transactional . try { {@org.acme.Item item}
flightService.makeBooking("BA123 ..."); <!DOCTYPE html>
taxiService.makeBooking("East Coast Taxis ..."); <html>
@Transactional
<head>
@NestedTopLevel
aa.commit(); <meta charset="UTF-8">
public interface FlightService {
} catch (Exception e) { <title>{item.name}</title>
int getNumberOfBookings();
aa.abort(); </head>
void makeBooking(String details);
} <body>
}
} <h1>{item.name}</h1>
<div>Price: {item.price}</div>
{#if item.price > 100}
The pessimistic strategy is the default one, you can change to <div>Discounted Price: {item.discountedPrice}</div>
optimistic by using @Optimistic . Quartz {/if}
</body>
Then you need to create the object inside org.jboss.stm.Container . Quarkus integrates with Quartz to schedule periodic clustered </html>
tasks.
Container<FlightService> container = new Container<>();
FlightServiceImpl instance = new FlightServiceImpl(); ./mvnw quarkus:add-extension First line is not mandatory but helps on doing property checks at
FlightService flightServiceProxy = container.create(instanc -Dextensions="quartz" compilation time.
e);
To render the template: Full list of con guration properties having quarkus.log as pre x: Spring DI
sentry.enable
public class Item { Quarkus provides a compatibility layer for Spring dependency
public String name; Enable the Sentry logging extension (default: false) injection.
public BigDecimal price;
} sentry.dsn
./mvnw quarkus:add-extension
Where to send events. -Dextensions="quarkus-spring-di"
@Inject
io.quarkus.qute.Template item; sentry.level

Log level (default: WARN ) Some examples of what you can do. Notice that annotations are
@GET
@Path("{id}") the Spring original ones.
sentry.in-app-packages
@Produces(MediaType.TEXT_HTML)
public TemplateInstance get(@PathParam("id") Integer id) { Con gure which package pre xes your application uses. @Configuration
return item.data("item", service.findItem(id)); public class AppConfiguration {
}
@Bean(name = "capitalizeFunction")
@TemplateExtension public StringFunction capitalizer() {
static BigDecimal discountedPrice(Item item) { return String::toUpperCase;
return item.price.multiply(new BigDecimal("0.9")); }
} }

Or as a component:
If @ResourcePath is not used in Template then the name of the eld is
used as le name. In this case the le should be
@Component("noopFunction")
src/main/resources/templates/item.{} . Extension of the le is not
public class NoOpSingleStringFunction
required to be set.
implements StringFunction {
discountedPrice
is not a eld of the POJO but a method call. }
Method de nition must be annotated with @TemplateExtension . First
paramter is used to match thebase object.
Also as a service and injection properties from
You can render programmaticaly too: application.properties .

// file located at src/main/resources/templates/reports/v1/


@Service
report_01.{}
public class MessageProducer {
@ResourcePath("reports/v1/report_01")

Template report;
@Value("${greeting.message}")

String message;
String output = report

.data("samples", service.get())
}
.render();

And you can inject using Autowired or constructor in a component


Sentry and in a JAX-RS resource too.

Quarkus integrates with Sentry for logging errors into an error @Component
monitoring system. public class GreeterBean {

./mvnw quarkus:add-extension private final MessageProducer messageProducer;
-Dextensions="quarkus-logging-sentry"
@Autowired @Qualifier("noopFunction")
StringFunction noopStringFunction;

And the con guration to send all errors occuring in the package
public GreeterBean(MessageProducer messageProducer) {
org.example to Sentrty with DSN https://abcd@sentry.io/1234 :
this.messageProducer = messageProducer;
}
quarkus.log.sentry=true }
quarkus.log.sentry.dsn=https://abcd@sentry.io/1234
quarkus.log.sentry.level=ERROR
quarkus.log.sentry.in-app-packages=org.example
Spring Web ./mvnw quarkus:add-extension
public interface FruitRepository -Dextensions="spring-security"
Quarkus provides a compatibility layer for Spring Web. extends CrudRepository<Fruit, Long> {
List<Fruit> findByColor(String color);
}
./mvnw quarkus:add-extension You need to choose a security extension to de ne user, roles, …
-Dextensions="quarkus-spring-web" such as openid-connect , oauth2 , properties-file or security-jdbc
as seen at RBAC.
And then you can inject it either as shown in Spring DI or in Spring
Web. Then you can use Spring Security annotations to protect the
Speci cally supports the REST related features. Notice that
infrastructure things like BeanPostProcessor will not be executed. methods:
Interfaces supported:

org.springframework.data.repository.Repository @Secured("admin")
@RestController
@GetMapping
@RequestMapping("/greeting")
org.springframework.data.repository.CrudRepository public String hello() {
public class GreetingController {
return "hello";

org.springframework.data.repository.PagingAndSortingReposito }
private final GreetingBean greetingBean;
ry

public GreetingController(GreetingBean greetingBean) {
org.springframework.data.jpa.repository.JpaRepository .
this.greetingBean = greetingBean; Quarkus provides support for some of the most used features of
} INFO: Generated repositories are automatically annotated with Spring Security’s @PreAuthorize annotation.
@Transactional .
@GetMapping("/{name}") Some examples:
public Greeting hello(@PathVariable(name = "name") Repository fragments is also supported:
String name) { hasRole
return new Greeting(greetingBean.greet(name));
public interface PersonRepository @PreAuthorize("hasRole('admin')")
}
extends JpaRepository<Person, Long>, PersonFragment {
}
@PreAuthorize("hasRole(@roles.USER)") where roles is a bean
void makeNameUpperCase(Person person); de ned with @Component annotation and USER is a public eld
} of the class.
Supported annotations are: RestController , RequestMapping ,
GetMapping , PostMapping , PutMapping , DeleteMapping , PatchMapping , hasAnyRole
RequestParam , RequestHeader , MatrixVariable , PathVariable ,
User de ned queries:
CookieValue , RequestBody , ResponseStatus , ExceptionHandler and @PreAuthorize("hasAnyRole(@roles.USER, 'view')")
RestControllerAdvice .
@Query("select m from Movie m where m.rating = ?1") Permit and Deny All
If you scaffold the project with spring-web extension, then Iterator<Movie> findByRating(String rating);
@PreAuthorize("permitAll()")
Spring Web annotations are sed in the generated project.
mvn io.quarkus:quarkus-maven-plugin:1.1.0.Final:create …
- @Modifying
@PreAuthorize("denyAll()")
Dextensions="spring-web" . @Query("delete from Movie where rating = :rating")
void deleteByRating(@Param("rating") String rating);
Anonymous and Authenticated
The next return types are supported:
org.springframework.http.ResponseEntity and java.util.Map . @PreAuthorize("isAnonymous()")
What is currently unsupported:
The next parameter types are supported: An Exception argument @PreAuthorize("isAuthenticated()")
and ServletRequest / HttpServletRequest (adding quarkus-undertow Methods of
dependency). org.springframework.data.repository.query.QueryByExampleExec Expressions
utor
Checks if the current logged in user is the same as the
Spring Data JPA username method parameter:
QueryDSL support
While users are encouraged to use Hibernate ORM with Panache
Customizing the base repository @PreAuthorize("#person.name == authentication.principal.use
for Relational Database access, Quarkus provides a compatibility
layer for Spring Data JPA repositories. rname")
java.util.concurrent.Future as return type
public void doSomethingElse(Person person){}

./mvnw quarkus:add-extension Native and named queries when using @Query


-Dextensions="quarkus-spring-data-jpa"
Spring Security Checks if calling a method if user can access:

INFO: Of course you still need to add the JDBC driver, and con gure Quarkus provides a compatibility layer for Spring Security.
it in application.properties .
@PreAuthorize("@personChecker.check(#person, authenticatio Resources
n.principal.username)")
public void doSomething(Person person){} https://quarkus.io/guides/

@Component https://www.youtube.com/user/lordofthejars
public class PersonChecker {
public boolean check(Person person, String username) { Authors :
return person.getName().equals(username);
} @alexsotob
} Java Champion and Director of DevExp at Red Hat

1.1.0.Final

Combining expressions:

@PreAuthorize("hasAnyRole('user', 'admin') AND #user == pri


ncipal.username")
public void allowedForUser(String user) {}

Potrebbero piacerti anche