Skip to content

Commit 173e0d7

Browse files
authored
Merge pull request #49420 from gsmet/3.25.2-backports-1
[3.25] 3.25.2 backports 1
2 parents d1199be + 477856d commit 173e0d7

File tree

32 files changed

+530
-57
lines changed

32 files changed

+530
-57
lines changed

core/deployment/src/main/java/io/quarkus/runner/bootstrap/StartupActionImpl.java

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ public class StartupActionImpl implements StartupAction {
5858
private final String mainClassName;
5959
private final String applicationClassName;
6060
private final Map<String, String> devServicesProperties;
61+
private volatile boolean devServicesStarted = false;
6162
private final List<DevServicesResultBuildItem> devServicesResults;
6263
private final List<DevServicesCustomizerBuildItem> devServicesCustomizers;
6364
private final String devServicesNetworkId;
@@ -111,7 +112,7 @@ public StartupActionImpl(CuratedApplication curatedApplication, BuildResult buil
111112
*/
112113
public RunningQuarkusApplication runMainClass(String... args) throws Exception {
113114
// Start dev services that weren't started in the augmentation phase
114-
startDevServices(devServicesRegistry, devServicesResults, devServicesCustomizers);
115+
ensureDevServicesStarted();
115116

116117
//first we hack around class loading in the fork join pool
117118
ForkJoinClassLoading.setForkJoinClassLoader(runtimeClassLoader);
@@ -202,6 +203,7 @@ public void addRuntimeCloseTask(Closeable closeTask) {
202203
}
203204

204205
private void doClose() {
206+
devServicesStarted = false;
205207
try {
206208
runtimeClassLoader.loadClass(Quarkus.class.getName()).getMethod("blockingExit").invoke(null);
207209
} catch (InvocationTargetException | NoSuchMethodException | IllegalAccessException
@@ -220,7 +222,7 @@ private void doClose() {
220222
@Override
221223
public int runMainClassBlocking(String... args) throws Exception {
222224
// Start dev services that weren't started in the augmentation phase
223-
startDevServices(devServicesRegistry, devServicesResults, devServicesCustomizers);
225+
ensureDevServicesStarted();
224226

225227
//first we hack around class loading in the fork join pool
226228
ForkJoinClassLoading.setForkJoinClassLoader(runtimeClassLoader);
@@ -292,15 +294,19 @@ public void overrideConfig(Map<String, String> config) {
292294
RuntimeOverrideConfigSource.setConfig(runtimeClassLoader, config);
293295
}
294296

295-
private void startDevServices(DevServicesRegistryBuildItem devServicesRegistry,
296-
List<DevServicesResultBuildItem> devServicesRequests,
297-
List<DevServicesCustomizerBuildItem> customizers) {
297+
private void ensureDevServicesStarted() {
298+
if (devServicesStarted) {
299+
return;
300+
}
301+
devServicesStarted = true;
298302
if (devServicesRegistry != null) {
299303
QuarkusClassLoader augmentClassLoader = curatedApplication.getAugmentClassLoader();
300304
if (augmentClassLoader == null) {
301305
throw new IllegalStateException("Dev services cannot be started without an augmentation class loader.");
302306
}
303-
devServicesRegistry.startAll(devServicesRequests, customizers, augmentClassLoader);
307+
devServicesRegistry.startAll(devServicesResults, devServicesCustomizers, augmentClassLoader);
308+
309+
devServicesProperties.putAll(devServicesRegistry.getConfigForAllRunningServices());
304310
}
305311
if (InitialConfigurator.DELAYED_HANDLER.isActivated()) {
306312
InitialConfigurator.DELAYED_HANDLER.buildTimeComplete();
@@ -312,7 +318,7 @@ private void startDevServices(DevServicesRegistryBuildItem devServicesRegistry,
312318
*/
313319
public RunningQuarkusApplication run(String... args) throws Exception {
314320
// Start dev services that weren't started in the augmentation phase
315-
startDevServices(devServicesRegistry, devServicesResults, devServicesCustomizers);
321+
ensureDevServicesStarted();
316322

317323
//first we hack around class loading in the fork join pool
318324
ForkJoinClassLoading.setForkJoinClassLoader(runtimeClassLoader);
@@ -404,12 +410,14 @@ public QuarkusClassLoader getClassLoader() {
404410
}
405411

406412
@Override
407-
public Map<String, String> getDevServicesProperties() {
413+
public Map<String, String> getOrInitialiseDevServicesProperties() {
414+
ensureDevServicesStarted();
408415
return devServicesProperties;
409416
}
410417

411418
@Override
412-
public String getDevServicesNetworkId() {
419+
public String getOrInitialiseDevServicesNetworkId() {
420+
ensureDevServicesStarted();
413421
return devServicesNetworkId;
414422
}
415423

devtools/config-doc-maven-plugin/pom.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,10 @@
117117
<groupId>io.quarkus.qute</groupId>
118118
<artifactId>qute-core</artifactId>
119119
</dependency>
120+
<dependency>
121+
<groupId>io.smallrye.config</groupId>
122+
<artifactId>smallrye-config-common</artifactId>
123+
</dependency>
120124
<dependency>
121125
<groupId>javax.inject</groupId>
122126
<artifactId>javax.inject</artifactId>

devtools/config-doc-maven-plugin/src/main/java/io/quarkus/maven/config/doc/generator/AbstractFormatter.java

Lines changed: 32 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

33
import java.text.Normalizer;
44
import java.time.Duration;
5+
import java.util.Arrays;
6+
import java.util.List;
7+
import java.util.Map.Entry;
58
import java.util.Optional;
69
import java.util.stream.Collectors;
710

@@ -16,6 +19,7 @@
1619
import io.quarkus.annotation.processor.documentation.config.util.Types;
1720
import io.quarkus.maven.config.doc.GenerateConfigDocMojo.Context;
1821
import io.quarkus.maven.config.doc.generator.GenerationReport.ConfigPropertyGenerationViolation;
22+
import io.smallrye.config.common.utils.StringUtil;
1923

2024
abstract class AbstractFormatter implements Formatter {
2125

@@ -112,23 +116,14 @@ public String formatDefaultValue(ConfigProperty configProperty) {
112116
return null;
113117
}
114118

115-
if (configProperty.isEnum() && enableEnumTooltips) {
116-
Optional<String> enumConstant = configProperty.getEnumAcceptedValues().values().entrySet().stream()
117-
.filter(e -> e.getValue().configValue().equals(defaultValue))
118-
.map(e -> e.getKey())
119-
.findFirst();
120-
121-
if (enumConstant.isPresent()) {
122-
Optional<JavadocElement> javadocElement = javadocRepository.getElement(configProperty.getType(),
123-
enumConstant.get());
124-
125-
if (javadocElement.isPresent()) {
126-
return tooltip(defaultValue, javadocElement.get().description());
127-
}
128-
}
119+
List<String> defaultValues;
120+
if (configProperty.isList()) {
121+
defaultValues = Arrays.asList(StringUtil.split(defaultValue));
122+
} else {
123+
defaultValues = List.of(defaultValue);
129124
}
130125

131-
return "`" + defaultValue + "`";
126+
return defaultValues.stream().map(v -> formatSingleDefaultValue(configProperty, v)).collect(Collectors.joining(", "));
132127
}
133128

134129
@Override
@@ -240,6 +235,26 @@ public String formatName(Extension extension) {
240235
return extension.name();
241236
}
242237

238+
private String formatSingleDefaultValue(ConfigProperty configProperty, String defaultValue) {
239+
if (configProperty.isEnum() && enableEnumTooltips) {
240+
Optional<String> enumConstant = configProperty.getEnumAcceptedValues().values().entrySet().stream()
241+
.filter(e -> e.getValue().configValue().equals(defaultValue))
242+
.map(Entry::getKey)
243+
.findFirst();
244+
245+
if (enumConstant.isPresent()) {
246+
Optional<JavadocElement> javadocElement = javadocRepository.getElement(configProperty.getType(),
247+
enumConstant.get());
248+
249+
if (javadocElement.isPresent()) {
250+
return tooltip(defaultValue, javadocElement.get().description());
251+
}
252+
}
253+
}
254+
255+
return escapeDefaultValue(defaultValue);
256+
}
257+
243258
private static String trimFinalDot(String javadoc) {
244259
if (javadoc == null || javadoc.isBlank()) {
245260
return null;
@@ -262,4 +277,6 @@ private static String trimFinalDot(String javadoc) {
262277
protected abstract String link(String href, String description);
263278

264279
protected abstract String tooltip(String value, String javadocDescription);
280+
281+
protected abstract String escapeDefaultValue(String defaultValue);
265282
}

devtools/config-doc-maven-plugin/src/main/java/io/quarkus/maven/config/doc/generator/AsciidocFormatter.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,4 +169,9 @@ private static String getQualifiedReference(String reference, String baseGuideUr
169169

170170
return baseGuideUrl + "#" + reference;
171171
}
172+
173+
@Override
174+
protected String escapeDefaultValue(String defaultValue) {
175+
return "`+++" + defaultValue + "+++`";
176+
}
172177
}

devtools/config-doc-maven-plugin/src/main/java/io/quarkus/maven/config/doc/generator/MarkdownFormatter.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,4 +38,9 @@ protected String tooltip(String value, String javadocDescription) {
3838
// we don't have tooltip support in Markdown
3939
return "`" + value + "`";
4040
}
41+
42+
@Override
43+
protected String escapeDefaultValue(String defaultValue) {
44+
return "```" + defaultValue + "```";
45+
}
4146
}

docs/src/main/asciidoc/rest-client.adoc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1382,7 +1382,7 @@ public class MyResponseExceptionMapper implements ResponseExceptionMapper<Runtim
13821382
@Override
13831383
public RuntimeException toThrowable(Response response) {
13841384
if (response.getStatus() == 500) {
1385-
throw new RuntimeException("The remote service responded with HTTP 500");
1385+
return new RuntimeException("The remote service responded with HTTP 500");
13861386
}
13871387
return null;
13881388
}
@@ -1392,7 +1392,7 @@ public class MyResponseExceptionMapper implements ResponseExceptionMapper<Runtim
13921392
`ResponseExceptionMapper` also defines the `getPriority` method which is used in order to determine the priority with which `ResponseExceptionMapper` implementations will be called (implementations with a lower value for `getPriority` will be invoked first).
13931393
If `toThrowable` returns an exception, then that exception will be thrown. If `null` is returned, the next implementation of `ResponseExceptionMapper` in the chain will be called (if there is any).
13941394

1395-
The class as written above, would not be automatically be used by any REST Client. To make it available to every REST Client of the application, the class needs to be annotated with `@Provider` (as long as `quarkus.rest-client.provider-autodiscovery` is not set to `false`).
1395+
The class as written above, would not be automatically used by any REST Client. To make it available to every REST Client of the application, the class needs to be annotated with `@Provider` (as long as `quarkus.rest-client.provider-autodiscovery` is not set to `false`).
13961396
Alternatively, if the exception handling class should only apply to specific REST Client interfaces, you can either annotate the interfaces with `@RegisterProvider(MyResponseExceptionMapper.class)`, or register it using configuration using the `providers` property of the proper `quarkus.rest-client` configuration group.
13971397

13981398
=== Using @ClientExceptionMapper

extensions/amazon-lambda/deployment/src/main/java/io/quarkus/amazon/lambda/deployment/AmazonLambdaProcessor.java

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,8 @@ List<AmazonLambdaBuildItem> discover(CombinedIndexBuildItem combinedIndexBuildIt
114114
final DotName name = info.name();
115115
final String lambda = name.toString();
116116
builder.addBeanClass(lambda);
117+
reflectiveClassBuildItemBuildProducer
118+
.produce(ReflectiveClassBuildItem.builder(lambda).methods().build());
117119

118120
String cdiName = null;
119121
AnnotationInstance named = info.declaredAnnotation(NAMED);
@@ -148,18 +150,9 @@ List<AmazonLambdaBuildItem> discover(CombinedIndexBuildItem combinedIndexBuildIt
148150
}
149151
}
150152
}
151-
if (!done) {
152-
current = combinedIndexBuildItem.getIndex().getClassByName(current.superName());
153-
}
154-
}
155-
if (done) {
156-
String handlerClass = current.name().toString();
157-
ret.add(new AmazonLambdaBuildItem(handlerClass, cdiName, streamHandler));
158-
reflectiveClassBuildItemBuildProducer.produce(ReflectiveClassBuildItem.builder(handlerClass).methods()
159-
.reason(getClass().getName()
160-
+ ": reflectively accessed in io.quarkus.amazon.lambda.runtime.AmazonLambdaRecorder.discoverHandlerMethod")
161-
.build());
153+
current = combinedIndexBuildItem.getIndex().getClassByName(current.superName());
162154
}
155+
ret.add(new AmazonLambdaBuildItem(lambda, cdiName, streamHandler));
163156
}
164157
additionalBeanBuildItemBuildProducer.produce(builder.build());
165158
reflectiveClassBuildItemBuildProducer
@@ -256,7 +249,7 @@ public void recordStaticInitHandlerClass(List<AmazonLambdaBuildItem> lambdas,
256249
}
257250
} else if (lambdas == null || lambdas.isEmpty()) {
258251
String errorMessage = "Unable to find handler class, make sure your deployment includes a single "
259-
+ RequestHandler.class.getName() + " or, " + RequestStreamHandler.class.getName() + " implementation";
252+
+ RequestHandler.class.getName() + " or " + RequestStreamHandler.class.getName() + " implementation";
260253
throw new RuntimeException(errorMessage);
261254
}
262255
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
package io.quarkus.amazon.lambda.deployment.testing;
2+
3+
import static io.restassured.RestAssured.given;
4+
import static org.hamcrest.CoreMatchers.containsString;
5+
6+
import jakarta.enterprise.context.ApplicationScoped;
7+
import jakarta.inject.Named;
8+
9+
import org.jboss.shrinkwrap.api.ShrinkWrap;
10+
import org.jboss.shrinkwrap.api.spec.JavaArchive;
11+
import org.junit.jupiter.api.Test;
12+
import org.junit.jupiter.api.extension.RegisterExtension;
13+
14+
import com.amazonaws.services.lambda.runtime.Context;
15+
import com.amazonaws.services.lambda.runtime.RequestHandler;
16+
17+
import io.quarkus.test.QuarkusUnitTest;
18+
19+
class LambdaWithHierarchyTest {
20+
21+
@RegisterExtension
22+
static final QuarkusUnitTest test = new QuarkusUnitTest().setArchiveProducer(() -> ShrinkWrap
23+
.create(JavaArchive.class)
24+
.addClasses(GreetingLambda.class, AbstractRequestHandler.class, Person.class));
25+
26+
// https://github.com/quarkusio/quarkus/issues/49413
27+
@Test
28+
public void testLambdaWithHierarchy() throws Exception {
29+
// you test your lambdas by invoking on http://localhost:8081
30+
// this works in dev mode too
31+
32+
Person in = new Person("dagrammy");
33+
given()
34+
.contentType("application/json")
35+
.accept("application/json")
36+
.body(in)
37+
.when()
38+
.post()
39+
.then()
40+
.statusCode(200)
41+
.body(containsString("Hello dagrammy"));
42+
}
43+
44+
@ApplicationScoped
45+
@Named("GreetingLambda")
46+
public static class GreetingLambda extends AbstractRequestHandler<Person, String> {
47+
48+
public String getName(Person input) {
49+
return "Hello " + input.getName();
50+
}
51+
52+
}
53+
54+
public static class Person {
55+
56+
private final String name;
57+
58+
public Person(String name) {
59+
this.name = name;
60+
}
61+
62+
public String getName() {
63+
return name;
64+
}
65+
}
66+
67+
public static abstract class AbstractRequestHandler<T, R> implements RequestHandler<T, R> {
68+
69+
@Override
70+
public R handleRequest(T input, Context context) {
71+
return getName(input);
72+
}
73+
74+
public abstract R getName(T input);
75+
}
76+
}

extensions/amazon-lambda/runtime/src/main/java/io/quarkus/amazon/lambda/runtime/AmazonLambdaRecorder.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ public static void handle(InputStream inputStream, OutputStream outputStream, Co
8888
}
8989

9090
private static Method discoverHandlerMethod(Class<? extends RequestHandler<?, ?>> handlerClass) {
91-
final Method[] methods = handlerClass.getDeclaredMethods();
91+
final Method[] methods = handlerClass.getMethods();
9292
Method method = null;
9393
for (int i = 0; i < methods.length && method == null; i++) {
9494
if (methods[i].getName().equals("handleRequest")) {

independent-projects/bootstrap/core/src/main/java/io/quarkus/bootstrap/app/StartupAction.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,15 @@ public interface StartupAction {
1717

1818
QuarkusClassLoader getClassLoader();
1919

20-
Map<String, String> getDevServicesProperties();
20+
/**
21+
* This will start any dev services that were not started in the augmentation phase.
22+
*/
23+
Map<String, String> getOrInitialiseDevServicesProperties();
2124

22-
String getDevServicesNetworkId();
25+
/**
26+
* This will start any dev services that were not started in the augmentation phase.
27+
*/
28+
String getOrInitialiseDevServicesNetworkId();
2329

2430
/**
2531
* Runs the application by running the main method of the main class. As this is a blocking method a new

0 commit comments

Comments
 (0)