Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

2.12.0 backports 1 without gradle #27476

Merged
merged 33 commits into from Aug 24, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
1338b41
Avoid SQL Server JDBC driver to load ANTLR parsers
Sanne Aug 17, 2022
debd78b
Bump smallrye-open-api from 2.1.23 to 2.2.0
MikeEdgar Aug 9, 2022
e1ad34c
Update OpenAPI auto-tag processing to account for SR 2.2.0 changes
MikeEdgar Aug 11, 2022
01e082b
Update smallrye-open-api Jakarta rewrite version to 3.0.0-RC3
MikeEdgar Aug 17, 2022
ebc9612
Make it more obvious how to do propagation.
pilhuhn Aug 18, 2022
e9edb60
Fix https://github.com/quarkusio/quarkus/issues/27344 - Remove refere…
cescoffier Aug 18, 2022
66a0f5c
Do not set 'realm=Quarkus' in Basic auth challenge
sberyozkin Aug 17, 2022
6d6ce54
Exclude com.microsoft.azure:msal4j from the application BOM
Sanne Aug 17, 2022
310a719
Fix how certificates are obtained in the RestClient integration tests
Ladicek Aug 18, 2022
f06bb8a
Remove useless @JsonProperty in MongoDB with Panache guide
loicmathieu Aug 17, 2022
29e9656
Dev UI - qute - fix table of discovered templates
mkouba Aug 19, 2022
7888736
Fix rest-json.adoc
IgnasiCR Aug 19, 2022
a3eec83
Bump postgresql from 42.4.1 to 42.4.2
dependabot[bot] Aug 21, 2022
7eaac36
Modify extension on reactive-sql-clients.adoc
IgnasiCR Aug 20, 2022
017416d
Jackson: also detect class referenced by `@JsonTypeIdResolver`
snazy Aug 18, 2022
4ba3726
Prevent duplicate HTTP headers when WriterInterceptor is used
geoand Aug 22, 2022
fd76207
Complete implementation of UriInfoImpl
geoand Aug 22, 2022
baa5289
Fix misleading DevUI score for void return types
geoand Aug 22, 2022
d0d142b
Bump kotlinx-serialization-json from 1.3.3 to 1.4.0
dependabot[bot] Aug 19, 2022
86b2cb0
Resume REST Client Reactive request handling on error if suspended
michalszynkiewicz Aug 19, 2022
921fbc3
Make @ClientExceptionMapper work with Kotlin
geoand Aug 22, 2022
54520ba
Update the Redis dev service to Redis 7.
cescoffier Aug 22, 2022
c347904
Remove @Blocking from the rest client guide
loicmathieu Aug 23, 2022
251396f
Minor fixes in codestart doc
ia3andy Aug 22, 2022
062b991
Make HelloRouterTest more robust
gsmet Aug 18, 2022
0dc251a
Deprecate OidcSession#expiresIn and add new methods
sberyozkin Aug 17, 2022
afe4b95
Add SPI for native for Error Code and Exception Name providers
phillip-kruger Aug 23, 2022
ade5f81
Fix Quarkiverse template build and release
ia3andy Jul 6, 2022
ac06932
Revert "Mark Quartz extension as stable"
gsmet Aug 23, 2022
9c4a92c
Add system properties source to CodeGenerator config sources
geoand Aug 23, 2022
d742975
Add support for optimistic locking in the new Redis API.
cescoffier Aug 19, 2022
3257492
Fix Redis channel subscription issue when there is no context available.
cescoffier Aug 18, 2022
d85cf96
Make sending OIDC client id with introspection credentials optional
sberyozkin Aug 23, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
12 changes: 9 additions & 3 deletions bom/application/pom.xml
Expand Up @@ -43,7 +43,7 @@
<smallrye-config.version>2.11.1</smallrye-config.version>
<smallrye-health.version>3.2.1</smallrye-health.version>
<smallrye-metrics.version>3.0.5</smallrye-metrics.version>
<smallrye-open-api.version>2.1.23</smallrye-open-api.version>
<smallrye-open-api.version>2.2.0</smallrye-open-api.version>
<smallrye-graphql.version>1.7.0</smallrye-graphql.version>
<smallrye-opentracing.version>2.1.1</smallrye-opentracing.version>
<smallrye-fault-tolerance.version>5.5.0</smallrye-fault-tolerance.version>
Expand Down Expand Up @@ -117,7 +117,7 @@
<cronutils.version>9.2.0</cronutils.version>
<quartz.version>2.3.2</quartz.version>
<h2.version>2.1.214</h2.version>
<postgresql-jdbc.version>42.4.1</postgresql-jdbc.version>
<postgresql-jdbc.version>42.4.2</postgresql-jdbc.version>
<mariadb-jdbc.version>3.0.7</mariadb-jdbc.version>
<mysql-jdbc.version>8.0.30</mysql-jdbc.version>
<mssql-jdbc.version>11.2.0.jre11</mssql-jdbc.version>
Expand Down Expand Up @@ -150,7 +150,7 @@
<azure-functions-java-library.version>1.4.2</azure-functions-java-library.version>
<kotlin.version>1.7.10</kotlin.version>
<kotlin.coroutine.version>1.6.4</kotlin.coroutine.version>
<kotlin-serialization.version>1.3.3</kotlin-serialization.version>
<kotlin-serialization.version>1.4.0</kotlin-serialization.version>
<kubernetes-client.version>5.12.3</kubernetes-client.version> <!-- Please check with Java Operator SDK team before updating -->
<dekorate.version>2.11.0</dekorate.version> <!-- Please check with Java Operator SDK team before updating -->
<maven-invoker.version>3.2.0</maven-invoker.version>
Expand Down Expand Up @@ -4955,6 +4955,12 @@
<groupId>com.microsoft.sqlserver</groupId>
<artifactId>mssql-jdbc</artifactId>
<version>${mssql-jdbc.version}</version>
<exclusions>
<exclusion>
<groupId>com.microsoft.azure</groupId>
<artifactId>msal4j</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
Expand Down
1 change: 1 addition & 0 deletions build-parent/pom.xml
Expand Up @@ -130,6 +130,7 @@
<maven-invoker-plugin.version>3.2.2</maven-invoker-plugin.version>
<maven-resources-plugin.version>3.1.0</maven-resources-plugin.version>
<maven-dependency-plugin.version>3.1.2</maven-dependency-plugin.version>
<truststore-maven-plugin.version>3.0.0</truststore-maven-plugin.version>

<!-- Webjars used by the Dev UI -->
<webjar.bootstrap.version>4.6.1</webjar.bootstrap.version>
Expand Down
Expand Up @@ -21,6 +21,7 @@
import io.quarkus.runtime.configuration.ConfigUtils;
import io.smallrye.config.PropertiesConfigSource;
import io.smallrye.config.SmallRyeConfig;
import io.smallrye.config.SysPropConfigSource;

/**
* A set of methods to initialize and execute {@link CodeGenProvider}s.
Expand Down Expand Up @@ -149,14 +150,15 @@ public static boolean trigger(ClassLoader deploymentClassLoader,
return callWithClassloader(deploymentClassLoader, () -> {

final PropertiesConfigSource pcs = new PropertiesConfigSource(properties, "Build system");
final SysPropConfigSource spcs = new SysPropConfigSource();

// Discovered Config classes may cause issues here, because this goal runs before compile
final SmallRyeConfig config = ConfigUtils.configBuilder(false, false, launchMode)
.setAddDiscoveredSources(false)
.setAddDiscoveredInterceptors(false)
.setAddDiscoveredConverters(false)
.withProfile(launchMode.getDefaultProfile())
.withSources(pcs)
.withSources(pcs, spcs)
.build();

CodeGenProvider provider = data.provider;
Expand Down
10 changes: 6 additions & 4 deletions docs/src/main/asciidoc/extension-codestart.adoc
Expand Up @@ -69,6 +69,8 @@ The https://github.com/quarkusio/quarkus/tree/main/independent-projects/tools/ba

== Writing an Extension Codestart

Here is a step-by-step guide to write an extension codestart. You may also watch the https://www.youtube.com/watch?v=lLyVDqVK8cE[Quarkus Insight #99] with a live-coding session.

As was mentioned previously, the base project files (pom.xml, Dockerfiles, ...) are already generated by the base codestarts provided by the Quarkus core. Thanks to this, we can only focus on the starter code specific to the extension.

Let's take `io.quarkiverse.aloha:quarkus-aloha` as an example extension GAV (don't look for this extension, it doesn't exist).
Expand Down Expand Up @@ -148,7 +150,7 @@ metadata:
artifact: "io.quarkiverse.aloha:quarkus-aloha:codestarts:jar:${project.version}"
----

* Add the readme <<readme-md>> section template in `base/readme.tpl.qute.md`:
* Add the readme <<readme-md>> section template in `base/README.tpl.qute.md`:
+
[source,html]
----
Expand All @@ -157,11 +159,11 @@ metadata:

* Run `mvn clean install` in the extension root (or just `runtime`).

* Now we can check that the codestart actually works by creating a project consuming our extension:
* Now we can check that the codestart actually works by creating a project consuming our extension (make sure the snapshot version is correct):
+
[source,bash]
----
quarkus create app aloha-app x=io.quarkiverse.aloha:quarkus-aloha:999-SNAPSHOT
quarkus create app aloha-app -x=io.quarkiverse.aloha:quarkus-aloha:999-SNAPSHOT

...
applying codestarts...
Expand Down Expand Up @@ -353,7 +355,7 @@ Those templates are able to use data which contains:
You may add a `README.md` or `README.tpl.qute.md` in the `base` directory, it will be appended to the others.
So just add the info relative to your extension codestart.

base/readme.tpl.qute.md
base/README.tpl.qute.md
[source,html]
----
{#include readme-header /}
Expand Down
1 change: 0 additions & 1 deletion docs/src/main/asciidoc/mongodb-panache.adoc
Expand Up @@ -183,7 +183,6 @@ If you need to write accessors, you can:
----
public class Person extends PanacheMongoEntity {

@JsonProperty
public String name;
public LocalDate birth;
public Status status;
Expand Down
5 changes: 3 additions & 2 deletions docs/src/main/asciidoc/opentelemetry.adoc
Expand Up @@ -424,10 +424,11 @@ we are able to propagate the span into the Kafka Record with:

[source,java]
----
Metadata.of(TracingMetadata.withPrevious(Context.current()));
TracingMetadata tm = TracingMetadata.withPrevious(Context.current();
Message out = Message.of(...).withMetadata(tm);
----

The above creates a `Metadata` object we can add to the `Message` being produced,
The above creates a `TracingMetadata` object we can add to the `Message` being produced,
which retrieves the OpenTelemetry `Context` to extract the current span for propagation.

[[configuration-reference]]
Expand Down
3 changes: 3 additions & 0 deletions docs/src/main/asciidoc/quartz.adoc
Expand Up @@ -6,10 +6,13 @@ https://github.com/quarkusio/quarkus/tree/main/docs/src/main/asciidoc
= Scheduling Periodic Tasks with Quartz

include::./attributes.adoc[]
:extension-status: preview

Modern applications often need to run specific tasks periodically.
In this guide, you learn how to schedule periodic clustered tasks using the http://www.quartz-scheduler.org/[Quartz] extension.

include::{includes}/extension-status.adoc[]

TIP: If you only need to run in-memory scheduler use the xref:scheduler.adoc[Scheduler] extension.

== Prerequisites
Expand Down
2 changes: 1 addition & 1 deletion docs/src/main/asciidoc/reactive-sql-clients.adoc
Expand Up @@ -114,7 +114,7 @@ If you are not familiar with Mutiny, check xref:mutiny-primer.adoc[Mutiny - an i
We will expose `Fruit` instances over HTTP in the JSON format.
Consequently, you also need to add the `quarkus-resteasy-reactive-jackson` extension:

:add-extension-extensions: resteasy-jackson
:add-extension-extensions: resteasy-reactive-jackson
include::{includes}/devtools/extension-add.adoc[]

If you prefer not to use the command line, manually add the dependency to your build file:
Expand Down
59 changes: 54 additions & 5 deletions docs/src/main/asciidoc/redis-reference.adoc
Expand Up @@ -31,8 +31,8 @@ In your `pom.xml` file, add:
.pom.xml
----
<dependency>
<groupId>io.quarkiverse.redis</groupId>
<artifactId>quarkus-redis</artifactId>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-redis-client</artifactId>
</dependency>
----

Expand Down Expand Up @@ -78,7 +78,7 @@ It exposes the `io.quarkus.redis.datasource.RedisDataSource` interface.
To help you select the suitable API for you, here are some recommendations:

* If you are building an imperative (_classic_) Quarkus application integrating with Redis: use `io.quarkus.redis.datasource.RedisDataSource`.
* If you are building a reactive Quarkus application integrating with Redis: use `io.quarkus.redis.datasource.RedisReactiveDataSource`.
* If you are building a reactive Quarkus application integrating with Redis: use `io.quarkus.redis.datasource.ReactiveRedisDataSource`.
* If you need fine-grain control, or execute commands in a generic way: use `io.vertx.mutiny.redis.client.RedisAPI`
* If you have existing Vert.x code, use `io.vertx.redis.client.RedisAPI`
* If you need to emit custom commands, you can either use the data sources (reactive or imperative) or the `io.vertx.mutiny.redis.client.Redis`.
Expand All @@ -104,7 +104,7 @@ When using the default connection, you can inject the various APIS using a _plai
----
@ApplicationScoped
public class RedisExample {
@Inject RedisReactiveDataSource reactiveDataSource;
@Inject ReactiveRedisDataSource reactiveDataSource;
@Inject RedisDataSource redisDataSource;
@Inject RedisAPI redisAPI;
// ...
Expand All @@ -128,7 +128,7 @@ To access the APIs, you need to use the `@RedisClientName` qualifier:
----
@ApplicationScoped
public class RedisExample {
@Inject @RedisClientName("my-redis-1") RedisReactiveDataSource reactiveDataSource;
@Inject @RedisClientName("my-redis-1") ReactiveRedisDataSource reactiveDataSource;
@Inject @RedisClientName("my-redis-2") RedisDataSource redisDataSource;
// ...
}
Expand Down Expand Up @@ -573,6 +573,55 @@ TransactionResult result = ds.withTransaction(tx -> {

IMPORTANT: You cannot use the pub/sub feature from within a transaction.

==== Using optimistic locking

To use optimistic locking, you need to use a variant of the `withTransaction` method, allowing the execution of code before the transaction starts.
In other words, it will be executed as follows:

[source]
----
WATCH key

// Pre-transaction block
// ....
// Produce a result

MULTI
// In transaction code, receive the result produced by the pre-transaction block.
EXEC
----

For example, if you need to update a value in a hash only if the field exists, you will use the following API:

[source, java]
----
OptimisticLockingTransactionResult<Boolean> result = blocking.withTransaction(ds -> {
// The pre-transaction block:
HashCommands<String, String, String> hashCommands = ds.hash(String.class);
return hashCommands.hexists(key, "field"); // Produce a result (boolean in this case)
},
(exists, tx) -> { // The transactional block, receives the result and the transactional data source
if (exists) {
tx.hash(String.class).hset(key, "field", "new value");
} else {
tx.discard();
}
},
key); // The watched key
----

If one of the watched keys is touched before or during the execution of the pre-transaction or transactional blocks, the transaction is aborted.
The pre-transactional block produces a result that the transactional block can use.
This construct is necessary because, within a transaction, the commands do not produce a result.
Results can only be retrieved after the execution of the transaction.

The pre-transaction and transactional blocks are invoked on the same Redis connection.
Consequently, the pre-transaction block must use the passed data source to execute commands.
Thus, the commands are emitted from that connection.
These commands must not modify the watched keys.

The transaction is aborted if the pre-transaction block throws an exception (or produces a failure when using the reactive API).

==== Executing custom commands

To execute a custom command, or a command not supported by the API, use the following approach:
Expand Down
11 changes: 3 additions & 8 deletions docs/src/main/asciidoc/rest-client-reactive.adoc
Expand Up @@ -247,7 +247,6 @@ Create the `src/main/java/org/acme/rest/client/ExtensionsResource.java` file wit
----
package org.acme.rest.client;

import io.smallrye.common.annotation.Blocking;
import org.eclipse.microprofile.rest.client.inject.RestClient;

import javax.ws.rs.GET;
Expand All @@ -263,7 +262,6 @@ public class ExtensionsResource {

@GET
@Path("/id/{id}")
@Blocking // <2>
public Set<Extension> id(String id) {
return extensionsService.getById(id);
}
Expand All @@ -273,7 +271,6 @@ public class ExtensionsResource {
There are two interesting parts in this listing:

<1> the client stub is injected with the `@RestClient` annotation instead of the usual CDI `@Inject`
<2> the call we are making with the client is blocking, hence we need the `@Blocking` annotation on the REST endpoint

== Programmatic client creation with RestClientBuilder

Expand Down Expand Up @@ -408,7 +405,6 @@ Open the `src/main/java/org/acme/rest/client/ExtensionsResource.java` file and u
----
package org.acme.rest.client;

import io.smallrye.common.annotation.Blocking;
import org.eclipse.microprofile.rest.client.inject.RestClient;

import javax.ws.rs.GET;
Expand All @@ -425,7 +421,6 @@ public class ExtensionsResource {

@GET
@Path("/id/{id}")
@Blocking
public Set<Extension> id(String id) {
return extensionsService.getById(id);
}
Expand All @@ -438,9 +433,9 @@ public class ExtensionsResource {
}
----

Please note that since the invocation is now non-blocking, we don't need the `@Blocking` annotation anymore on the endpoint.
This means that the `idAsync` method will be invoked on the event loop, i.e. will not get offloaded to a worker pool thread
and thus reducing hardware resource utilization.
Please note that since the invocation is now non-blocking, the `idAsync` method will be invoked on the event loop,
i.e. will not get offloaded to a worker pool thread and thus reducing hardware resource utilization.
See xref:resteasy-reactive.adoc#execution-model[Resteasy reactive execution model] for more details.


To test asynchronous methods, add the test method below in `ExtensionsResourceTest`:
Expand Down
5 changes: 0 additions & 5 deletions docs/src/main/asciidoc/rest-json.adoc
Expand Up @@ -420,16 +420,11 @@ import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.Set;

import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

@Path("/legumes")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public class LegumeResource {

private Set<Legume> legumes = Collections.synchronizedSet(new LinkedHashSet<>());
Expand Down
Expand Up @@ -30,6 +30,7 @@
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.annotation.JsonTypeIdResolver;
import com.fasterxml.jackson.databind.module.SimpleModule;

import io.quarkus.arc.deployment.AdditionalBeanBuildItem;
Expand Down Expand Up @@ -68,6 +69,8 @@ public class JacksonProcessor {

private static final DotName JSON_AUTO_DETECT = DotName.createSimple(JsonAutoDetect.class.getName());

private static final DotName JSON_TYPE_ID_RESOLVER = DotName.createSimple(JsonTypeIdResolver.class.getName());

private static final DotName JSON_CREATOR = DotName.createSimple("com.fasterxml.jackson.annotation.JsonCreator");

private static final DotName JSON_NAMING = DotName.createSimple("com.fasterxml.jackson.databind.annotation.JsonNaming");
Expand Down Expand Up @@ -185,13 +188,28 @@ void register(
}

for (AnnotationInstance creatorInstance : index.getAnnotations(JSON_AUTO_DETECT)) {
if (creatorInstance.target().kind().equals(CLASS)) {
if (creatorInstance.target().kind() == CLASS) {
reflectiveClass
.produce(
new ReflectiveClassBuildItem(true, true, creatorInstance.target().asClass().name().toString()));
}
}

// Register @JsonTypeIdResolver implementations for reflection.
// Note: @JsonTypeIdResolver is, simply speaking, the "dynamic version" of @JsonSubTypes, i.e. sub-types are
// dynamically identified by Jackson's `TypeIdResolver.typeFromId()`, which returns sub-types of the annotated
// class. Means: the referenced `TypeIdResolver` _and_ all sub-types of the annotated class must be registered
// for reflection.
for (AnnotationInstance resolverInstance : index.getAnnotations(JSON_TYPE_ID_RESOLVER)) {
AnnotationValue value = resolverInstance.value("value");
if (value != null) {
// Add the type-id-resolver class
reflectiveClass.produce(new ReflectiveClassBuildItem(true, true, value.asClass().name().toString()));
// Add the whole hierarchy of the annotated class
addReflectiveHierarchyClass(resolverInstance.target().asClass().name(), reflectiveHierarchyClass);
}
}

// make sure we register the constructors and methods marked with @JsonCreator for reflection
for (AnnotationInstance creatorInstance : index.getAnnotations(JSON_CREATOR)) {
if (METHOD == creatorInstance.target().kind()) {
Expand Down