Skip to content

Commit 330195e

Browse files
authored
Merge pull request #47721 from gsmet/3.22.2-backports-1
[3.22] 3.22.2 backports 1
2 parents 4e7adfb + d56cbe5 commit 330195e

File tree

49 files changed

+453
-176
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+453
-176
lines changed

.github/workflows/ci-actions-incremental.yml

+2-1
Original file line numberDiff line numberDiff line change
@@ -1221,7 +1221,8 @@ jobs:
12211221
# Ignore the following YAML Schema error
12221222
timeout-minutes: ${{matrix.timeout}}
12231223
strategy:
1224-
max-parallel: ${{ fromJson(needs.configure.outputs.config).maxParallel || 12 }}
1224+
# fully disable for now as we have issues with RunsOn and it might come from the value being defined (even if set to 999)
1225+
#max-parallel: ${{ fromJson(needs.configure.outputs.config).maxParallel || 12 }}
12251226
fail-fast: false
12261227
matrix: ${{ fromJson(needs.calculate-test-jobs.outputs.native_matrix) }}
12271228
steps:

docs/src/main/asciidoc/_includes/extension-status.adoc

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
ifdef::extension-status[]
12
[NOTE]
23
====
34
This technology is considered {extension-status}.
@@ -21,3 +22,4 @@ endif::[]
2122

2223
For a full list of possible statuses, check our https://quarkus.io/faq/#what-are-the-extension-statuses[FAQ entry].
2324
====
25+
endif::[]

docs/src/main/asciidoc/building-native-image.adoc

+3-3
Original file line numberDiff line numberDiff line change
@@ -75,10 +75,10 @@ This is particularly important when it comes to conformance and security.
7575

7676
* Mandrel is recommended for building native executables that target Linux containerized environments.
7777
This means that Mandrel users are encouraged to use containers to build their native executables.
78-
If you are building native executables for macOS,
78+
If you are building native executables for macOS on amd64/x86,
7979
you should consider using Oracle GraalVM instead,
8080
because Mandrel does not currently target this platform.
81-
Building native executables directly on bare metal Linux or Windows is possible,
81+
Building native executables directly on bare metal Linux, macOS (on M processors), or Windows is possible,
8282
with details available in the https://github.com/graalvm/mandrel/blob/default/README.md[Mandrel README]
8383
and https://github.com/graalvm/mandrel/releases[Mandrel releases].
8484

@@ -111,7 +111,7 @@ We recommend the _community edition_ of GraalVM. For example, install it with `s
111111
export GRAALVM_HOME=$HOME/Development/mandrel/
112112
----
113113
+
114-
On macOS (not supported by Mandrel), point the variable to the `Home` sub-directory:
114+
On macOS (amd64/x86 based Macs not supported), point the variable to the `Home` sub-directory:
115115
+
116116
[source,bash]
117117
----

docs/src/main/asciidoc/deploying-to-openshift-docker-howto.adoc

+1-1
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ openshift-helloworld openshift-helloworld-username-dev.apps.sandbox-m2.ll9k.p1
145145
Be aware that the route is now listening on port 80 and is no longer on port 8080.
146146
====
147147
+
148-
You can test the application demonstrated in this example with a web browser or a terminal by using `curl` and the complete URL output from `oc get routes`, that is, "\http://openshift-helloworld-username-dev.apps.sandbox-m2.ll9k.p1.openshiftapps.com".
148+
You can test the application demonstrated in this example with a web browser or a terminal by using `curl` and the complete URL output from `oc get routes`, that is, `\http://openshift-helloworld-username-dev.apps.sandbox-m2.ll9k.p1.openshiftapps.com`.
149149
+
150150
For example: `curl \http://openshift-helloworld-username-dev.apps.sandbox-m2.ll9k.p1.openshiftapps.com`.
151151

docs/src/main/asciidoc/getting-started-testing.adoc

+1-1
Original file line numberDiff line numberDiff line change
@@ -1431,7 +1431,7 @@ An example use of this could be the following Maven command, that forces `@Quark
14311431
./mvnw verify -Dquarkus.http.test-host=1.2.3.4 -Dquarkus.http.test-port=4321
14321432
----
14331433

1434-
To test against a running instance that only accepts SSL/TLS connection (example: `https://1.2.3.4:4321`) set the system property `quarkus.http.test-ssl-enabled` to `true`.
1434+
To test against a running instance that only accepts SSL/TLS connection (example: `https://1.2.3.4:4321`) set the system property `quarkus.http.test-ssl-enabled` to `true` and `quarkus.http.test-ssl-port` to the target HTTPS port.
14351435

14361436
== Mixing `@QuarkusTest` with other type of tests
14371437

docs/src/main/asciidoc/security-openid-connect-dev-services.adoc

+5
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,11 @@ KeyCloak Dev Services Starting:
4242
2021-11-02 17:14:44,170 INFO [io.qua.oid.dep.dev.key.KeycloakDevServicesProcessor] (build-10) Dev Services for Keycloak started.
4343
----
4444

45+
[NOTE]
46+
====
47+
Adding the `quarkus.keycloak.devservices.java-opts=-XX:UseSVE=0` configuration property may help to workaround Keycloak Dev Services startup problems on some Mac OS systems.
48+
====
49+
4550
[IMPORTANT]
4651
====
4752
When logging in to the Keycloak admin console, the username is `admin`, and the password is `admin`.

docs/src/main/asciidoc/tls-registry-reference.adoc

+2-1
Original file line numberDiff line numberDiff line change
@@ -849,7 +849,8 @@ quarkus.tls.http.key-store.pem.0.key=tls.key
849849
[IMPORTANT]
850850
====
851851
Impacted servers and clients may need to listen to the `CertificateUpdatedEvent` to apply the new certificates.
852-
This is automatically done for the Quarkus HTTP server, such as the Quarkus REST server, gRPC server, and WebSocket server, as well as the management interface if it is enabled.
852+
This is automatically done for the Quarkus HTTP server, as well as the Quarkus REST server, gRPC server, and WebSocket server, as well as the management interface if it is enabled.
853+
On the client side, Quarkus REST Client automatically handles certificate update events.
853854
====
854855

855856
NOTE: In Quarkus dev mode, when files are touched, it will trigger the `CertificateUpdatedEvent` much more frequently.

docs/src/main/asciidoc/websockets-next-reference.adoc

-3
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ https://github.com/quarkusio/quarkus/tree/main/docs/src/main/asciidoc
55
////
66
[id="websockets-next-reference-guide"]
77
= WebSockets Next reference guide
8-
:extension-status: preview
98
include::_attributes.adoc[]
109
:numbered:
1110
:sectnums:
@@ -14,8 +13,6 @@ include::_attributes.adoc[]
1413
:topics: web,websockets
1514
:extensions: io.quarkus:quarkus-websockets-next
1615

17-
include::{includes}/extension-status.adoc[]
18-
1916
The `quarkus-websockets-next` extension provides a modern declarative API to define WebSocket server and client endpoints.
2017

2118
== The WebSocket protocol

docs/src/main/asciidoc/websockets-next-tutorial.adoc

-3
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,6 @@ include::_attributes.adoc[]
1414
This guide explains how your Quarkus application can utilize web sockets to create interactive web applications.
1515
In this guide, we will develop a very simple chat application using web sockets to receive and send messages to the other connected users.
1616

17-
include::{includes}/extension-status.adoc[]
18-
19-
2017
== Prerequisites
2118

2219
include::{includes}/prerequisites.adoc[]

docs/src/main/asciidoc/websockets.adoc

+10-2
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,22 @@ This guide is maintained in the main Quarkus repository
33
and pull requests should be submitted there:
44
https://github.com/quarkusio/quarkus/tree/main/docs/src/main/asciidoc
55
////
6-
= Using WebSockets
6+
= Using WebSockets with Undertow
77
include::_attributes.adoc[]
88
:categories: web
99
:summary: This guide explains how your Quarkus application can utilize web sockets to create interactive web applications. Because it’s the canonical web socket application, we are going to create a simple chat application.
1010
:topics: web,websockets
1111
:extensions: io.quarkus:quarkus-websockets,io.quarkus:quarkus-websockets-client
1212

13-
This guide explains how your Quarkus application can utilize web sockets to create interactive web applications.
13+
This guide explains how your Quarkus application can utilize web sockets to create interactive web applications,
14+
in the context of an Undertow-based Quarkus application, or if you rely on https://jakarta.ee/specifications/websocket/[Jakarta WebSocket].
15+
16+
[TIP]
17+
====
18+
If you don't use Undertow or https://jakarta.ee/specifications/websocket/[Jakarta WebSocket],
19+
it is recommended to use the more modern xref:websockets-next-tutorial.adoc[WebSockets Next extensions].
20+
====
21+
1422
Because it's the _canonical_ web socket application, we are going to create a simple chat application.
1523

1624
== Prerequisites

extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/ArcDevModeConfig.java

+11-3
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,17 @@ public interface ArcDevModeConfig {
1515
boolean monitoringEnabled();
1616

1717
/**
18-
* If set to true then the dependency graphs are generated and available in the Dev UI.
18+
* If set to {@code true} then the dependency graphs are generated and available in the Dev UI. If set to {@code auto}
19+
* then the dependency graphs are generated if there's less than 1000 beans in the application. If set to {@code false} the
20+
* dependency graphs are not generated.
1921
*/
20-
@WithDefault("true")
21-
boolean generateDependencyGraphs();
22+
@WithDefault("auto")
23+
GenerateDependencyGraphs generateDependencyGraphs();
24+
25+
public enum GenerateDependencyGraphs {
26+
TRUE,
27+
FALSE,
28+
AUTO
29+
}
2230

2331
}

extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/devui/ArcDevModeApiProcessor.java

+43-3
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
import java.util.Set;
1111
import java.util.stream.Collectors;
1212

13+
import org.jboss.logging.Logger;
14+
1315
import io.quarkus.arc.deployment.ArcConfig;
1416
import io.quarkus.arc.deployment.CompletedApplicationClassPredicateBuildItem;
1517
import io.quarkus.arc.deployment.ValidationPhaseBuildItem;
@@ -29,6 +31,19 @@
2931

3032
public class ArcDevModeApiProcessor {
3133

34+
private static final Logger LOG = Logger.getLogger(ArcDevModeApiProcessor.class);
35+
36+
/**
37+
* Do not generate dependency graphs for apps with more than N beans
38+
*/
39+
private static final int DEPENCENY_GRAPH_BEANS_LIMIT = 1000;
40+
41+
/**
42+
* If a dependency graph exceeds the limit then we apply the {@link DevBeanInfos#MAX_DEPENDENCY_LEVEL} and if still exceeds
43+
* the limit it's skipped completely, i.e. dependency graph is not available
44+
*/
45+
private static final int DEPENCENY_GRAPH_NODES_LIMIT = 30;
46+
3247
@BuildStep(onlyIf = IsDevelopment.class)
3348
public void collectBeanInfo(ArcConfig config, ValidationPhaseBuildItem validationPhaseBuildItem,
3449
CompletedApplicationClassPredicateBuildItem predicate,
@@ -65,7 +80,7 @@ public void collectBeanInfo(ArcConfig config, ValidationPhaseBuildItem validatio
6580

6681
// Build dependency graphs
6782
Map<String, List<String>> beanDependenciesMap = new HashMap<>();
68-
if (config.devMode().generateDependencyGraphs()) {
83+
if (generateDependencyGraphs(config, beanInfos)) {
6984
BeanResolver resolver = validationPhaseBuildItem.getBeanResolver();
7085
Collection<BeanInfo> beans = validationContext.get(BuildExtension.Key.BEANS);
7186
Map<BeanInfo, List<InjectionPointInfo>> directDependents = new HashMap<>();
@@ -85,11 +100,27 @@ public void collectBeanInfo(ArcConfig config, ValidationPhaseBuildItem validatio
85100
DependencyGraph dependencyGraph = buildDependencyGraph(bean, validationContext, resolver, beanInfos,
86101
allInjectionPoints, declaringToProducers,
87102
directDependents);
103+
if (dependencyGraph.links.isEmpty()) {
104+
// Skip the graph if no links exist
105+
continue;
106+
}
107+
if (dependencyGraph.nodes.size() > DEPENCENY_GRAPH_NODES_LIMIT) {
108+
DependencyGraph visibleGraph = dependencyGraph.forLevel(DevBeanInfos.DEFAULT_MAX_DEPENDENCY_LEVEL);
109+
if (visibleGraph.nodes.size() > DEPENCENY_GRAPH_NODES_LIMIT) {
110+
LOG.debugf("Skip dependency graph for %s - too many visible nodes: %s", bean,
111+
visibleGraph.nodes.size());
112+
continue;
113+
} else {
114+
LOG.debugf("Dependency graph for %s was reduced to visible nodes: %s", bean,
115+
dependencyGraph.nodes.size());
116+
dependencyGraph = visibleGraph;
117+
}
118+
}
88119
beanInfos.addDependencyGraph(bean.getIdentifier(), dependencyGraph);
89120
// id -> [dep1Id, dep2Id]
90121
beanDependenciesMap.put(bean.getIdentifier(),
91122
dependencyGraph.filterLinks(link -> link.type.equals("directDependency")).nodes.stream()
92-
.map(DevBeanInfo::getId).filter(id -> !id.equals(bean.getIdentifier()))
123+
.map(Node::getId).filter(id -> !id.equals(bean.getIdentifier()))
93124
.collect(Collectors.toList()));
94125
}
95126
}
@@ -111,7 +142,7 @@ DependencyGraph buildDependencyGraph(BeanInfo bean, ValidationContext validation
111142
addNodesDependencies(0, bean, nodes, links, bean, devBeanInfos);
112143
addNodesDependents(0, bean, nodes, links, bean, allInjectionPoints, declaringToProducers, resolver, devBeanInfos,
113144
directDependents);
114-
return new DependencyGraph(nodes, links);
145+
return new DependencyGraph(nodes.stream().map(Node::from).collect(Collectors.toSet()), links);
115146
}
116147

117148
private void addNodesDependencies(int level, BeanInfo root, Set<DevBeanInfo> nodes, Set<Link> links, BeanInfo bean,
@@ -184,4 +215,13 @@ private void addNodesDependents(int level, BeanInfo root, Set<DevBeanInfo> nodes
184215
}
185216
}
186217

218+
private boolean generateDependencyGraphs(ArcConfig config, DevBeanInfos beanInfos) {
219+
return switch (config.devMode().generateDependencyGraphs()) {
220+
case TRUE -> true;
221+
case FALSE -> false;
222+
case AUTO -> beanInfos.getBeans().size() < DEPENCENY_GRAPH_BEANS_LIMIT;
223+
default -> throw new IllegalArgumentException("Unexpected value: " + config.devMode().generateDependencyGraphs());
224+
};
225+
}
226+
187227
}

extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/devui/DependencyGraph.java

+4-4
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@ public class DependencyGraph {
88

99
static final DependencyGraph EMPTY = new DependencyGraph(Set.of(), Set.of());
1010

11-
public final Set<DevBeanInfo> nodes;
11+
public final Set<Node> nodes;
1212
public final Set<Link> links;
1313
public final int maxLevel;
1414

15-
public DependencyGraph(Set<DevBeanInfo> nodes, Set<Link> links) {
15+
public DependencyGraph(Set<Node> nodes, Set<Link> links) {
1616
this.nodes = nodes;
1717
this.links = links;
1818
this.maxLevel = links.stream().mapToInt(l -> l.level).max().orElse(0);
@@ -25,7 +25,7 @@ DependencyGraph forLevel(int level) {
2525
DependencyGraph filterLinks(Predicate<Link> predicate) {
2626
// Filter out links first
2727
Set<Link> newLinks = new HashSet<>();
28-
Set<DevBeanInfo> newNodes = new HashSet<>();
28+
Set<Node> newNodes = new HashSet<>();
2929
Set<String> usedIds = new HashSet<>();
3030
for (Link link : links) {
3131
if (predicate.test(link)) {
@@ -35,7 +35,7 @@ DependencyGraph filterLinks(Predicate<Link> predicate) {
3535
}
3636
}
3737
// Now keep only nodes for which a link exists...
38-
for (DevBeanInfo node : nodes) {
38+
for (Node node : nodes) {
3939
if (usedIds.contains(node.getId())) {
4040
newNodes.add(node);
4141
}

extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/devui/DevBeanInfos.java

+1
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ public DevInterceptorInfo getInterceptor(String id) {
9090
}
9191

9292
public DependencyGraph getDependencyGraph(String beanId) {
93+
// Note that MAX_DEPENDENCY_LEVEL is not implemented in UI yet
9394
Integer maxLevel = DevConsoleManager.getGlobal(MAX_DEPENDENCY_LEVEL);
9495
if (maxLevel == null) {
9596
maxLevel = DEFAULT_MAX_DEPENDENCY_LEVEL;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package io.quarkus.arc.deployment.devui;
2+
3+
public class Node {
4+
5+
static Node from(DevBeanInfo beanInfo) {
6+
return new Node(beanInfo.getId(), beanInfo.getDescription(), beanInfo.getSimpleDescription());
7+
}
8+
9+
private final String id;
10+
private final String description;
11+
private final String simpleDescription;
12+
13+
Node(String id, String description, String simpleDescription) {
14+
this.id = id;
15+
this.description = description;
16+
this.simpleDescription = simpleDescription;
17+
}
18+
19+
public String getId() {
20+
return id;
21+
}
22+
23+
public String getDescription() {
24+
return description;
25+
}
26+
27+
public String getSimpleDescription() {
28+
return simpleDescription;
29+
}
30+
31+
}

extensions/arc/deployment/src/main/resources/dev-ui/qwc-arc-bean-graph.js

-1
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,6 @@ export class QwcArcBeanGraph extends LitElement {
9292
}else {
9393
newNode.category = catindex;
9494
}
95-
//console.log('Adding node: ' + newNode.name);
9695
return this._nodes.push(newNode) - 1;
9796
}
9897
return index;

extensions/grpc/runtime/src/main/java/io/quarkus/grpc/runtime/GrpcServerRecorder.java

+5-2
Original file line numberDiff line numberDiff line change
@@ -142,8 +142,11 @@ public void initializeGrpcServer(boolean hasNoBindableServiceBeans, BeanContaine
142142
if (configuration.useSeparateServer()) {
143143
if (provider == null) {
144144
LOGGER.warn(
145-
"Using legacy gRPC support, with separate new HTTP server instance. " +
146-
"Switch to single HTTP server instance usage with quarkus.grpc.server.use-separate-server=false property");
145+
"""
146+
Using legacy gRPC support with a separate HTTP server instance. This is the current default to maintain compatibility.
147+
You can switch to the new unified HTTP server by setting quarkus.grpc.server.use-separate-server=false
148+
This change is recommended for new applications and will become the default in future versions.
149+
""");
147150
}
148151

149152
if (launchMode == LaunchMode.DEVELOPMENT) {

extensions/oidc-common/runtime/src/main/java/io/quarkus/oidc/common/runtime/ClientAssertionProvider.java

+5
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,11 @@ private ClientAssertion loadFromFileSystem() {
7575
if (Files.exists(bearerTokenPath)) {
7676
try {
7777
String bearerToken = Files.readString(bearerTokenPath).trim();
78+
if (bearerToken.isEmpty()) {
79+
LOG.error(String.format("Bearer token file at path %s is empty or contains only whitespace",
80+
bearerTokenPath));
81+
return null;
82+
}
7883
Long expiresAt = getExpiresAtFromExpClaim(bearerToken);
7984
if (expiresAt != null) {
8085
return new ClientAssertion(bearerToken, expiresAt, scheduleRefresh(expiresAt));

extensions/oidc-common/runtime/src/test/java/io/quarkus/oidc/common/runtime/ClientAssertionProviderTest.java

+20
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import static java.nio.file.StandardOpenOption.TRUNCATE_EXISTING;
55
import static java.nio.file.StandardOpenOption.WRITE;
66
import static org.junit.jupiter.api.Assertions.assertEquals;
7+
import static org.junit.jupiter.api.Assertions.assertNull;
78

89
import java.io.IOException;
910
import java.nio.file.Files;
@@ -40,6 +41,25 @@ public void testJwtBearerTokenRefresh() {
4041
}
4142
}
4243

44+
@Test
45+
public void EmptyBearerTokenFileShouldReturnNullClientAssertion() {
46+
Vertx vertx = Vertx.vertx();
47+
Path emptyTokenPath = Path.of("target").resolve("empty-jwt-bearer-token.json");
48+
49+
storeNewJwtBearerToken(emptyTokenPath, "");
50+
try (var clientAssertionProvider = new ClientAssertionProvider(vertx, emptyTokenPath)) {
51+
assertNull(clientAssertionProvider.getClientAssertion());
52+
53+
String validToken = createJwtBearerToken();
54+
storeNewJwtBearerToken(emptyTokenPath, validToken);
55+
56+
Awaitility.await().atMost(Duration.ofSeconds(10))
57+
.untilAsserted(() -> assertEquals(validToken, clientAssertionProvider.getClientAssertion()));
58+
} finally {
59+
vertx.close().toCompletionStage().toCompletableFuture().join();
60+
}
61+
}
62+
4363
private static void storeNewJwtBearerToken(Path jwtBearerTokenPath, String jwtBearerToken) {
4464
try {
4565
Files.writeString(jwtBearerTokenPath, jwtBearerToken, TRUNCATE_EXISTING, CREATE, WRITE);

extensions/quartz/deployment/src/main/java/io/quarkus/quartz/deployment/QuartzProcessor.java

+4-1
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,10 @@ List<ReflectiveClassBuildItem> reflectiveClasses(QuartzBuildTimeConfig config,
263263
reflectiveClasses.addAll(getAdditionalConfigurationReflectiveClasses(config.triggerListeners(), TriggerListener.class));
264264
reflectiveClasses.addAll(getAdditionalConfigurationReflectiveClasses(config.jobListeners(), JobListener.class));
265265
reflectiveClasses.addAll(getAdditionalConfigurationReflectiveClasses(config.plugins(), SchedulerPlugin.class));
266-
266+
reflectiveClasses
267+
.add(ReflectiveClassBuildItem.builder("io.quarkus.quartz.runtime.QuartzSchedulerImpl$NonconcurrentInvokerJob")
268+
.reason(getClass().getName())
269+
.methods().build());
267270
return reflectiveClasses;
268271
}
269272

0 commit comments

Comments
 (0)