Skip to content

Commit 7f01318

Browse files
authored
Merge pull request #50997 from gsmet/3.29.3-backports-1
[3.29] 3.29.3 backports 1
2 parents 6195a79 + 9ebd3b0 commit 7f01318

File tree

32 files changed

+602
-90
lines changed

32 files changed

+602
-90
lines changed

bom/application/pom.xml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,10 @@
1919
<bouncycastle.version>1.82</bouncycastle.version>
2020
<bouncycastle.fips.version>2.1.2</bouncycastle.fips.version>
2121
<bouncycastle.tls.fips.version>2.1.22</bouncycastle.tls.fips.version>
22-
<cyclonedx.version>9.0.5</cyclonedx.version>
22+
<cyclonedx.version>11.0.1</cyclonedx.version>
2323
<expressly.version>6.0.0</expressly.version>
2424
<findbugs.version>3.0.2</findbugs.version>
25-
<jandex.version>3.5.1</jandex.version>
25+
<jandex.version>3.5.2</jandex.version>
2626
<javax.annotation-api.version>1.3.2</javax.annotation-api.version>
2727
<javax.inject.version>1</javax.inject.version>
2828
<parsson.version>1.1.7</parsson.version>
@@ -97,7 +97,7 @@
9797
<classmate.version>1.7.1</classmate.version>
9898
<!-- See root POM for hibernate-orm.version, hibernate-reactive.version, hibernate-validator.version,
9999
hibernate-search.version, antlr.version, bytebuddy.version -->
100-
<narayana.version>7.3.0.Final</narayana.version>
100+
<narayana.version>7.3.3.Final</narayana.version>
101101
<narayana-lra.version>1.0.2.Final</narayana-lra.version>
102102
<agroal.version>2.8</agroal.version>
103103
<jboss-transaction-spi.version>8.0.0.Final</jboss-transaction-spi.version>
@@ -125,7 +125,7 @@
125125
<mysql-jdbc.version>8.3.0</mysql-jdbc.version>
126126
<mssql-jdbc.version>13.2.1.jre11</mssql-jdbc.version>
127127
<adal4j.version>1.6.7</adal4j.version>
128-
<oracle-jdbc.version>23.6.0.24.10</oracle-jdbc.version>
128+
<oracle-jdbc.version>23.26.0.0.0</oracle-jdbc.version>
129129
<derby-jdbc.version>10.16.1.1</derby-jdbc.version>
130130
<db2-jdbc.version>12.1.0.0</db2-jdbc.version>
131131
<shrinkwrap.version>1.2.6</shrinkwrap.version>

build-parent/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
<jboss-bridger-plugin.version>1.6.Final</jboss-bridger-plugin.version>
3131

3232
<!-- Jandex versions -->
33-
<jandex.version>3.5.1</jandex.version>
33+
<jandex.version>3.5.2</jandex.version>
3434
<jandex-gradle-plugin.version>1.0.0</jandex-gradle-plugin.version>
3535

3636
<asciidoctorj.version>2.5.13</asciidoctorj.version>

docs/src/main/asciidoc/gradle-tooling.adoc

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -798,10 +798,10 @@ plugins {
798798
799799
quarkus {
800800
buildForkOptions {
801-
maxHeapSize = '2g'
801+
maxHeapSize = "2g"
802802
}
803803
codeGenForkOptions {
804-
maxHeapSize = '128m'
804+
maxHeapSize = "128m"
805805
}
806806
}
807807
----
@@ -933,4 +933,4 @@ The current state of compatibility is shown in the following table:
933933
The approach to enable Quarkus conditional and extension build time (deployment) dependencies has changed in Quarkus 3.25.1 due to a few issues with the previous implementation.
934934
Specifically, the previous implementation would not apply relevant dependency exclusions to enabled conditional and deployment dependencies. It would also appear to leak devmode-only dependencies into non-devmode classpaths (such as test and prod) in some cases. These issues couldn't be fixed in a reasonable way in the previous implementation, which is why the Quarkus dependency resolution had to be re-implemented based on a different approach using link:https://docs.gradle.org/current/userguide/variant_aware_resolution.html[Gradle component variants].
935935

936-
The previous implementation still remains available for now in case the new one appears to introduce not yet detected regressions and can be enabled by setting `disableQuarkusComponentVariants` project property to `true`.
936+
The previous implementation still remains available for now in case the new one appears to introduce not yet detected regressions and can be enabled by setting `disableQuarkusComponentVariants` project property to `true`.

extensions/elasticsearch-rest-client-common/deployment/src/main/java/io/quarkus/elasticsearch/restclient/common/deployment/DevServicesElasticsearchProcessor.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -355,7 +355,7 @@ private DevservicesElasticsearchBuildItemsConfiguration(List<DevservicesElastics
355355
for (DevservicesElasticsearchBuildItem buildItem : buildItems) {
356356
if (version == null) {
357357
version = buildItem.getVersion();
358-
} else if (!version.equals(buildItem.getVersion())) {
358+
} else if (buildItem.getVersion() != null && !version.equals(buildItem.getVersion())) {
359359
// safety guard but should never occur as only Hibernate Search ORM Elasticsearch configure the version
360360
throw new BuildException(
361361
"Multiple extensions request different versions of Elasticsearch for Dev Services.",
@@ -364,7 +364,7 @@ private DevservicesElasticsearchBuildItemsConfiguration(List<DevservicesElastics
364364

365365
if (distribution == null) {
366366
distribution = buildItem.getDistribution();
367-
} else if (!distribution.equals(buildItem.getDistribution())) {
367+
} else if (buildItem.getDistribution() != null && !distribution.equals(buildItem.getDistribution())) {
368368
// safety guard but should never occur as only Hibernate Search ORM Elasticsearch configure the distribution
369369
throw new BuildException(
370370
"Multiple extensions request different distributions of Elasticsearch for Dev Services.",
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
package io.quarkus.grpc.server.interceptors;
2+
3+
import static org.assertj.core.api.Assertions.assertThatThrownBy;
4+
5+
import java.time.Duration;
6+
import java.util.logging.LogRecord;
7+
8+
import jakarta.enterprise.context.ApplicationScoped;
9+
10+
import org.assertj.core.api.Condition;
11+
import org.jboss.shrinkwrap.api.ShrinkWrap;
12+
import org.jboss.shrinkwrap.api.asset.StringAsset;
13+
import org.jboss.shrinkwrap.api.spec.JavaArchive;
14+
import org.junit.jupiter.api.Assertions;
15+
import org.junit.jupiter.api.Test;
16+
import org.junit.jupiter.api.extension.RegisterExtension;
17+
18+
import io.grpc.Metadata;
19+
import io.grpc.ServerCall;
20+
import io.grpc.ServerCallHandler;
21+
import io.grpc.ServerInterceptor;
22+
import io.grpc.Status;
23+
import io.grpc.StatusRuntimeException;
24+
import io.grpc.examples.helloworld.Greeter;
25+
import io.grpc.examples.helloworld.GreeterBean;
26+
import io.grpc.examples.helloworld.GreeterGrpc;
27+
import io.grpc.examples.helloworld.HelloReply;
28+
import io.grpc.examples.helloworld.HelloRequest;
29+
import io.quarkus.grpc.GlobalInterceptor;
30+
import io.quarkus.grpc.GrpcClient;
31+
import io.quarkus.grpc.server.services.HelloService;
32+
import io.quarkus.test.QuarkusUnitTest;
33+
import io.smallrye.mutiny.Uni;
34+
35+
public class ClosingCallInInterceptorTest {
36+
37+
private static final Metadata.Key<String> CLOSE_REASON_KEY = Metadata.Key.of("CUSTOM_CLOSE_REASON",
38+
Metadata.ASCII_STRING_MARSHALLER);
39+
private static final String STATED_REASON_TO_CLOSE = "Because I want to close it.";
40+
41+
@RegisterExtension
42+
static final QuarkusUnitTest config = new QuarkusUnitTest().setArchiveProducer(
43+
() -> ShrinkWrap.create(JavaArchive.class)
44+
.addPackage(GreeterGrpc.class.getPackage())
45+
.addClasses(MyClosingCallInterceptor.class, GreeterBean.class, HelloRequest.class, HelloService.class)
46+
.addAsResource(new StringAsset("quarkus.grpc.server.use-separate-server=false" + System.lineSeparator()),
47+
"application.properties"))
48+
.setLogRecordPredicate(
49+
record -> record.getMessage() != null && record.getMessage().contains("Closing gRPC call due to an error"))
50+
.assertLogRecords(logRecords -> {
51+
if (!logRecords.isEmpty()) {
52+
for (LogRecord logRecord : logRecords) {
53+
if (logRecord.getThrown() instanceof IllegalStateException ise
54+
&& ise.getMessage().contains("Already closed")) {
55+
Assertions.fail("Log contains message with 'java.lang.IllegalStateException: Already closed'");
56+
}
57+
}
58+
}
59+
});
60+
61+
@GrpcClient
62+
Greeter greeter;
63+
64+
@Test
65+
void test() {
66+
Uni<HelloReply> result = greeter.sayHello(HelloRequest.newBuilder().setName("ServiceA").build());
67+
assertThatThrownBy(() -> result.await().atMost(Duration.ofSeconds(4)))
68+
.isInstanceOf(StatusRuntimeException.class)
69+
.has(new Condition<Throwable>(t -> {
70+
if (t instanceof StatusRuntimeException statusRuntimeException) {
71+
var trailers = statusRuntimeException.getTrailers();
72+
if (trailers != null) {
73+
return STATED_REASON_TO_CLOSE.equals(trailers.get(CLOSE_REASON_KEY));
74+
}
75+
}
76+
return false;
77+
}, "Checking close reason returned in metadata"))
78+
.hasMessageContaining("UNAUTHENTICATED");
79+
}
80+
81+
@ApplicationScoped
82+
@GlobalInterceptor
83+
public static class MyClosingCallInterceptor implements ServerInterceptor {
84+
85+
@Override
86+
public <ReqT, RespT> ServerCall.Listener<ReqT> interceptCall(ServerCall<ReqT, RespT> call, Metadata headers,
87+
ServerCallHandler<ReqT, RespT> next) {
88+
var metadata = new Metadata();
89+
metadata.put(CLOSE_REASON_KEY, STATED_REASON_TO_CLOSE);
90+
call.close(Status.UNAUTHENTICATED, metadata);
91+
return new ServerCall.Listener<>() {
92+
};
93+
}
94+
}
95+
96+
}

extensions/grpc/runtime/src/main/java/io/quarkus/grpc/runtime/supports/context/GrpcDuplicatedContextGrpcInterceptor.java

Lines changed: 35 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,20 @@
55
import java.util.Optional;
66
import java.util.concurrent.atomic.AtomicBoolean;
77
import java.util.function.Consumer;
8-
import java.util.function.Supplier;
8+
import java.util.function.Function;
99

1010
import jakarta.enterprise.context.ApplicationScoped;
1111
import jakarta.enterprise.inject.spi.Prioritized;
1212
import jakarta.inject.Inject;
1313

1414
import org.jboss.logging.Logger;
1515

16+
import io.grpc.ForwardingServerCall;
1617
import io.grpc.Metadata;
1718
import io.grpc.ServerCall;
1819
import io.grpc.ServerCallHandler;
1920
import io.grpc.ServerInterceptor;
21+
import io.grpc.Status;
2022
import io.grpc.StatusException;
2123
import io.quarkus.grpc.ExceptionHandlerProvider;
2224
import io.quarkus.grpc.GlobalInterceptor;
@@ -54,15 +56,27 @@ public <ReqT, RespT> ServerCall.Listener<ReqT> interceptCall(ServerCall<ReqT, Re
5456
}
5557
}
5658

57-
private <ReqT, RespT> Supplier<ServerCall.Listener<ReqT>> nextCall(ServerCall<ReqT, RespT> call,
59+
private <ReqT, RespT> Function<Runnable, ServerCall.Listener<ReqT>> nextCall(ServerCall<ReqT, RespT> call,
5860
Metadata headers,
5961
ServerCallHandler<ReqT, RespT> next) {
6062
// Must be sure to call next.startCall on the right context
6163
io.grpc.Context current = io.grpc.Context.current();
62-
return () -> {
64+
return onClose -> {
6365
io.grpc.Context previous = current.attach();
6466
try {
65-
return next.startCall(call, headers);
67+
var forwardingCall = new ForwardingServerCall<ReqT, RespT>() {
68+
@Override
69+
protected ServerCall<ReqT, RespT> delegate() {
70+
return call;
71+
}
72+
73+
@Override
74+
public void close(Status status, Metadata trailers) {
75+
onClose.run();
76+
super.close(status, trailers);
77+
}
78+
};
79+
return next.startCall(forwardingCall, headers);
6680
} finally {
6781
current.detach(previous);
6882
}
@@ -77,31 +91,35 @@ public int getPriority() {
7791
static class ListenedOnDuplicatedContext<ReqT, RespT> extends ServerCall.Listener<ReqT> {
7892

7993
private final Context context;
80-
private final Supplier<ServerCall.Listener<ReqT>> supplier;
94+
private final Function<Runnable, ServerCall.Listener<ReqT>> listenerCreator;
8195
private final ExceptionHandlerProvider ehp;
8296
private final ServerCall<ReqT, RespT> call;
83-
private ServerCall.Listener<ReqT> delegate;
97+
private volatile ServerCall.Listener<ReqT> delegate;
8498

8599
private final AtomicBoolean closed = new AtomicBoolean();
86100

87101
public ListenedOnDuplicatedContext(
88102
ExceptionHandlerProvider ehp,
89-
ServerCall<ReqT, RespT> call, Supplier<ServerCall.Listener<ReqT>> supplier, Context context) {
103+
ServerCall<ReqT, RespT> call, Function<Runnable, ServerCall.Listener<ReqT>> listenerCreator, Context context) {
90104
this.ehp = ehp;
91105
this.context = context;
92-
this.supplier = supplier;
106+
this.listenerCreator = listenerCreator;
93107
this.call = call;
94108
}
95109

96-
private synchronized ServerCall.Listener<ReqT> getDelegate() {
97-
if (delegate == null) {
98-
try {
99-
delegate = supplier.get();
100-
} catch (Throwable t) {
101-
// If the interceptor supplier throws an exception, catch it, and close the call.
102-
log.warn("Unable to retrieve gRPC Server call listener, see the cause below.");
103-
close(t);
104-
return null;
110+
private ServerCall.Listener<ReqT> getDelegate() {
111+
if (delegate == null && !closed.get()) {
112+
synchronized (this) {
113+
if (delegate == null && !closed.get()) {
114+
try {
115+
delegate = listenerCreator.apply(() -> closed.set(true));
116+
} catch (Throwable t) {
117+
// If the interceptor supplier throws an exception, catch it, and close the call.
118+
log.warn("Unable to retrieve gRPC Server call listener, see the cause below.");
119+
close(t);
120+
return null;
121+
}
122+
}
105123
}
106124
}
107125
return delegate;

extensions/kafka-client/runtime-dev/pom.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,10 @@
1818
<groupId>io.quarkus</groupId>
1919
<artifactId>quarkus-kafka-client</artifactId>
2020
</dependency>
21+
<dependency>
22+
<groupId>org.junit.jupiter</groupId>
23+
<artifactId>junit-jupiter</artifactId>
24+
<scope>test</scope>
25+
</dependency>
2126
</dependencies>
2227
</project>

extensions/kafka-client/runtime-dev/src/main/java/io/quarkus/kafka/client/runtime/dev/ui/model/converter/KafkaModelConverter.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ public KafkaMessage convert(ConsumerRecord<Bytes, Bytes> message) {
3030

3131
private static Map<String, String> headers(ConsumerRecord<Bytes, Bytes> message) {
3232
return StreamSupport.stream(message.headers().spliterator(), false)
33-
.collect(Collectors.toMap(Header::key, header -> new String(header.value(), StandardCharsets.UTF_8)));
33+
.collect(Collectors.toMap(Header::key, header -> new String(header.value(), StandardCharsets.UTF_8),
34+
(existing, replacement) -> replacement));
3435
}
3536
}

0 commit comments

Comments
 (0)