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.14.0 backports 1 #28909

Merged
merged 36 commits into from
Oct 31, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
2c7dc68
Add a validate capability to Flyway
geoand Oct 26, 2022
475da0d
Propagate headers from `@ClientHeaderParam` when using ClientHeadersFact
Sgitario Oct 26, 2022
1913971
Include more kinds of lists in test parameter converter support
geoand Oct 19, 2022
1de2f57
Upgrade various Jakarta-related versions
gsmet Oct 26, 2022
3774335
Jakarta - Handle Jakarta EL addition separately
gsmet Oct 26, 2022
284db3a
Allow configuring Ingress rules
Sgitario Oct 25, 2022
129c4b0
Fail project create for invalid artifact/group id
ebullient Oct 26, 2022
f565094
Docs: Use major.minor part of GraalVM version only
zakkak Oct 26, 2022
bb752b9
Docs: Drop references to Java 8 for JVM mode and Java 11 for native
zakkak Oct 26, 2022
954d6a5
Docs: Update external links to GraalVM documentation
zakkak Oct 26, 2022
9eb343a
Docs: Move graal/mandrel version-for-documentation properties to docs…
zakkak Oct 26, 2022
3fb7490
Fix deduced value for @RestHeader without a value
geoand Oct 26, 2022
4f7a426
Add test for client usage of @RestHeader on the Reactive REST Client
geoand Oct 26, 2022
8b4cf68
Qute fragments - unify API and simplify UX
mkouba Oct 24, 2022
1f9bc1c
Fix compatibility with Redis 5
cescoffier Oct 26, 2022
6510ac4
Slightly optimize the number of allocations in Cache + Arc integration
geoand Oct 27, 2022
09857ce
Detect callback methods (such as methods annotated with @PostConstruc…
cescoffier Oct 24, 2022
dabd042
Add native memory management section to native reference guide
galderz Oct 13, 2022
3467e9d
Fix GraalVM documentation URLs
galderz Oct 26, 2022
28bf171
Bump kafka-oauth-client from 0.10.0 to 0.11.0
vsevel Oct 27, 2022
7489f51
Mark Spring Data REST extension as stable in documentation
Sgitario Oct 28, 2022
7368cc5
Ban ConfigSourceFactory implementations from the source codegen phase
aloubyansky Oct 24, 2022
00c3202
Fix typo in security-getting-started.adoc
kdnakt Oct 28, 2022
a0be44f
RESTEasyReactive: support `@Rest*` annotations on bean params for the…
FroMage Oct 26, 2022
5eb9747
Ensure that JAX-RS Providers type is accessible without an request
geoand Oct 27, 2022
f219984
Remove clearing out the request scope from RESTEasy Reactive coroutin…
geoand Oct 27, 2022
efc802e
Bump smallrye-common-bom from 1.13.1 to 1.13.2
dependabot[bot] Oct 27, 2022
0b5a5b5
Throw an IllegalStateException with basic info about the provider tha…
aloubyansky Oct 19, 2022
7ba619c
Support PathFilters for PathTree's representing archives
aloubyansky Oct 27, 2022
f8da3c5
Docs - reactive SQL clients also supports service binding
michalvavrik Oct 31, 2022
f2ac852
Support programmatic `multipart/form-data` responses
Sgitario Oct 26, 2022
9ddc51c
Use non closeable output stream for writting the multipart entities
Sgitario Oct 31, 2022
4f0dbd2
Qute - fix type resolution for extension methods
michalvavrik Oct 28, 2022
37f33e1
Disable relevant parts of Panache when Hibernate ORM/Reactive is disa…
yrodiere Oct 26, 2022
b85f700
Test Panache-ORM/Reactive with Hibernate ORM/Reactive disabled
yrodiere Oct 26, 2022
b78106d
Prevent null pointer in setAllHeaders
Sgitario Oct 31, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions bom/application/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
<microprofile-rest-client.version>2.0</microprofile-rest-client.version>
<microprofile-jwt.version>1.2</microprofile-jwt.version>
<microprofile-lra.version>1.0</microprofile-lra.version>
<smallrye-common.version>1.13.1</smallrye-common.version>
<smallrye-common.version>1.13.2</smallrye-common.version>
<smallrye-config.version>2.12.1</smallrye-config.version>
<smallrye-health.version>3.3.0</smallrye-health.version>
<smallrye-metrics.version>3.0.5</smallrye-metrics.version>
Expand Down Expand Up @@ -201,7 +201,7 @@
<aesh-readline.version>2.2</aesh-readline.version>
<aesh.version>2.6</aesh.version>
<!-- these two artifacts needs to be compatible together -->
<strimzi-oauth.version>0.10.0</strimzi-oauth.version>
<strimzi-oauth.version>0.11.0</strimzi-oauth.version>
<strimzi-oauth.nimbus.version>9.25.6</strimzi-oauth.nimbus.version>
<java-buildpack-client.version>0.0.6</java-buildpack-client.version>
<org-crac.version>0.1.1</org-crac.version>
Expand Down Expand Up @@ -6156,6 +6156,7 @@
<recipe>io.quarkus.maven.javax.managed</recipe>
<recipe>io.quarkus.maven.javax.versions</recipe>
<recipe>io.quarkus.jakarta-versions</recipe>
<recipe>io.quarkus.jakarta-el</recipe>
<recipe>io.quarkus.jakarta-jaxrs-jaxb</recipe>
<recipe>io.quarkus.jakarta-security</recipe>
<recipe>io.quarkus.smallrye</recipe>
Expand Down
5 changes: 0 additions & 5 deletions build-parent/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,6 @@
<jandex-gradle-plugin.version>1.0.0</jandex-gradle-plugin.version>

<!-- These properties are needed in order for them to be resolvable by the documentation -->
<!-- The Graal version we suggest using in documentation - as that's
what we work with by self downloading it: -->
<graal-sdk.version-for-documentation>22.2.0</graal-sdk.version-for-documentation>
<mandrel.version-for-documentation>22.2</mandrel.version-for-documentation>

<asciidoctorj.version>2.5.7</asciidoctorj.version>
<htmlunit.version>2.40.0</htmlunit.version>
<javaparser-core.version>3.24.2</javaparser-core.version>
Expand Down
124 changes: 92 additions & 32 deletions core/deployment/src/main/java/io/quarkus/deployment/CodeGenerator.java
Original file line number Diff line number Diff line change
@@ -1,30 +1,35 @@
package io.quarkus.deployment;

import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.ServiceLoader;
import java.util.StringJoiner;
import java.util.function.Consumer;

import org.eclipse.microprofile.config.Config;

import io.quarkus.bootstrap.classloading.ClassPathElement;
import io.quarkus.bootstrap.classloading.FilteredClassPathElement;
import io.quarkus.bootstrap.classloading.MemoryClassPathElement;
import io.quarkus.bootstrap.classloading.QuarkusClassLoader;
import io.quarkus.bootstrap.model.ApplicationModel;
import io.quarkus.bootstrap.prebuild.CodeGenException;
import io.quarkus.deployment.codegen.CodeGenData;
import io.quarkus.deployment.dev.DevModeContext;
import io.quarkus.deployment.dev.DevModeContext.ModuleInfo;
import io.quarkus.maven.dependency.ResolvedDependency;
import io.quarkus.paths.OpenPathTree;
import io.quarkus.paths.PathCollection;
import io.quarkus.runtime.LaunchMode;
import io.quarkus.runtime.configuration.ConfigUtils;
import io.quarkus.runtime.util.ClassPathUtils;
import io.smallrye.config.KeyMap;
import io.smallrye.config.KeyMapBackedConfigSource;
import io.smallrye.config.NameIterator;
Expand All @@ -37,7 +42,9 @@
*/
public class CodeGenerator {

private static final String MP_CONFIG_SPI_CONFIG_SOURCE_PROVIDER = "META-INF/services/org.eclipse.microprofile.config.spi.ConfigSourceProvider";
private static final List<String> CONFIG_SOURCE_FACTORY_INTERFACES = List.of(
"META-INF/services/io.smallrye.config.ConfigSourceFactory",
"META-INF/services/org.eclipse.microprofile.config.spi.ConfigSourceProvider");

// used by Gradle and Maven
public static void initAndRun(QuarkusClassLoader classLoader,
Expand Down Expand Up @@ -113,6 +120,7 @@ public static List<CodeGenData> init(ClassLoader deploymentClassLoader, Collecti
});
}

@SuppressWarnings("unchecked")
private static List<CodeGenProvider> loadCodeGenProviders(ClassLoader deploymentClassLoader)
throws CodeGenException {
Class<? extends CodeGenProvider> codeGenProviderClass;
Expand Down Expand Up @@ -174,42 +182,94 @@ public static boolean trigger(ClassLoader deploymentClassLoader,
public static Config getConfig(ApplicationModel appModel, LaunchMode launchMode, Properties buildSystemProps,
QuarkusClassLoader deploymentClassLoader) throws CodeGenException {
// Config instance that is returned by this method should be as close to the one built in the ExtensionLoader as possible
if (appModel.getAppArtifact().getContentTree()
.contains(MP_CONFIG_SPI_CONFIG_SOURCE_PROVIDER)) {
final List<ClassPathElement> allElements = ((QuarkusClassLoader) deploymentClassLoader).getAllElements(false);
// we don't want to load config sources from the current module because they haven't been compiled yet
final QuarkusClassLoader.Builder configClBuilder = QuarkusClassLoader
.builder("CodeGenerator Config ClassLoader", QuarkusClassLoader.getSystemClassLoader(), false);
final Collection<Path> appRoots = appModel.getAppArtifact().getContentTree().getRoots();
for (ClassPathElement e : allElements) {
if (appRoots.contains(e.getRoot())) {
configClBuilder.addElement(new FilteredClassPathElement(e, List.of(MP_CONFIG_SPI_CONFIG_SOURCE_PROVIDER)));
final Map<String, List<String>> appModuleConfigFactories = getConfigSourceFactoryImpl(appModel.getAppArtifact());
if (!appModuleConfigFactories.isEmpty()) {
final Map<String, List<String>> allConfigFactories = new HashMap<>(appModuleConfigFactories.size());
final Map<String, byte[]> allowedConfigFactories = new HashMap<>(appModuleConfigFactories.size());
final Map<String, byte[]> bannedConfigFactories = new HashMap<>(appModuleConfigFactories.size());
for (Map.Entry<String, List<String>> appModuleFactories : appModuleConfigFactories.entrySet()) {
final String factoryImpl = appModuleFactories.getKey();
try {
ClassPathUtils.consumeAsPaths(deploymentClassLoader, factoryImpl, p -> {
try {
allConfigFactories.computeIfAbsent(factoryImpl, k -> new ArrayList<>())
.addAll(Files.readAllLines(p));
} catch (IOException e) {
throw new UncheckedIOException("Failed to read " + p, e);
}
});
} catch (IOException e) {
throw new CodeGenException("Failed to read resources from classpath", e);
}
final List<String> allFactories = allConfigFactories.getOrDefault(factoryImpl, List.of());
allFactories.removeAll(appModuleFactories.getValue());
if (allFactories.isEmpty()) {
bannedConfigFactories.put(factoryImpl, new byte[0]);
} else {
configClBuilder.addElement(e);
final StringJoiner joiner = new StringJoiner(System.lineSeparator());
allFactories.forEach(f -> joiner.add(f));
allowedConfigFactories.put(factoryImpl, joiner.toString().getBytes());
}
}

// we don't want to load config source factories/providers from the current module because they haven't been compiled yet
QuarkusClassLoader.Builder configClBuilder = QuarkusClassLoader.builder("CodeGenerator Config ClassLoader",
deploymentClassLoader, false);
if (!allowedConfigFactories.isEmpty()) {
configClBuilder.addElement(new MemoryClassPathElement(allowedConfigFactories, true));
}
if (!bannedConfigFactories.isEmpty()) {
configClBuilder.addBannedElement(new MemoryClassPathElement(bannedConfigFactories, true));
}
deploymentClassLoader = configClBuilder.build();
}
final SmallRyeConfigBuilder builder = ConfigUtils.configBuilder(false, launchMode)
.forClassLoader(deploymentClassLoader);
final PropertiesConfigSource pcs = new PropertiesConfigSource(buildSystemProps, "Build system");
final SysPropConfigSource spcs = new SysPropConfigSource();

final Map<String, String> platformProperties = appModel.getPlatformProperties();
if (platformProperties.isEmpty()) {
builder.withSources(pcs, spcs);
} else {
final KeyMap<String> props = new KeyMap<>(platformProperties.size());
for (Map.Entry<String, String> prop : platformProperties.entrySet()) {
props.findOrAdd(new NameIterator(prop.getKey())).putRootValue(prop.getValue());
try {
final SmallRyeConfigBuilder builder = ConfigUtils.configBuilder(false, launchMode)
.forClassLoader(deploymentClassLoader);
final PropertiesConfigSource pcs = new PropertiesConfigSource(buildSystemProps, "Build system");
final SysPropConfigSource spcs = new SysPropConfigSource();

final Map<String, String> platformProperties = appModel.getPlatformProperties();
if (platformProperties.isEmpty()) {
builder.withSources(pcs, spcs);
} else {
final KeyMap<String> props = new KeyMap<>(platformProperties.size());
for (Map.Entry<String, String> prop : platformProperties.entrySet()) {
props.findOrAdd(new NameIterator(prop.getKey())).putRootValue(prop.getValue());
}
final KeyMapBackedConfigSource platformConfigSource = new KeyMapBackedConfigSource("Quarkus platform",
// Our default value configuration source is using an ordinal of Integer.MIN_VALUE
// (see io.quarkus.deployment.configuration.DefaultValuesConfigurationSource)
Integer.MIN_VALUE + 1000, props);
builder.withSources(platformConfigSource, pcs, spcs);
}
final KeyMapBackedConfigSource platformConfigSource = new KeyMapBackedConfigSource("Quarkus platform",
// Our default value configuration source is using an ordinal of Integer.MIN_VALUE
// (see io.quarkus.deployment.configuration.DefaultValuesConfigurationSource)
Integer.MIN_VALUE + 1000, props);
builder.withSources(platformConfigSource, pcs, spcs);
return builder.build();
} finally {
if (!appModuleConfigFactories.isEmpty()) {
deploymentClassLoader.close();
}
}
}

private static Map<String, List<String>> getConfigSourceFactoryImpl(ResolvedDependency dep) throws CodeGenException {
final Map<String, List<String>> configFactoryImpl = new HashMap<>(CONFIG_SOURCE_FACTORY_INTERFACES.size());
try (OpenPathTree openTree = dep.getContentTree().open()) {
for (String s : CONFIG_SOURCE_FACTORY_INTERFACES) {
openTree.accept(s, v -> {
if (v == null) {
return;
}
try {
configFactoryImpl.put(s, Files.readAllLines(v.getPath()));
} catch (IOException e) {
throw new UncheckedIOException("Failed to read " + v.getPath(), e);
}
});
}
} catch (IOException e) {
throw new CodeGenException("Failed to read " + dep.getResolvedPaths(), e);
}
return builder.build();
return configFactoryImpl;
}

private static Path codeGenOutDir(Path generatedSourcesDir,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
package io.quarkus.cli.create;

import java.util.regex.Pattern;

import io.quarkus.devtools.commands.CreateProjectHelper;
import picocli.CommandLine;
import picocli.CommandLine.TypeConversionException;

public class TargetGAVGroup {
static final String BAD_IDENTIFIER = "The specified %s identifier (%s) contains invalid characters. Valid characters are alphanumeric (A-Za-z), underscore, dash and dot.";
static final Pattern OK_ID = Pattern.compile("[0-9A-Za-z_.-]+");

static final String DEFAULT_GAV = CreateProjectHelper.DEFAULT_GROUP_ID + ":"
+ CreateProjectHelper.DEFAULT_ARTIFACT_ID + ":"
+ CreateProjectHelper.DEFAULT_VERSION;
Expand Down Expand Up @@ -52,6 +58,13 @@ void projectGav() {
}
}
}
if (artifactId != CreateProjectHelper.DEFAULT_ARTIFACT_ID && !OK_ID.matcher(artifactId).matches()) {
throw new TypeConversionException(String.format(BAD_IDENTIFIER, "artifactId", artifactId));
}
if (groupId != CreateProjectHelper.DEFAULT_GROUP_ID && !OK_ID.matcher(groupId).matches()) {
throw new TypeConversionException(String.format(BAD_IDENTIFIER, "groupId", groupId));
}

initialized = true;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import org.junit.jupiter.api.Test;

import io.quarkus.devtools.commands.CreateProjectHelper;
import picocli.CommandLine.TypeConversionException;

public class TargetGAVGroupTest {

Expand Down Expand Up @@ -92,4 +93,16 @@ void testOldParameters() {
Assertions.assertEquals("a", gav.getArtifactId());
Assertions.assertEquals("v", gav.getVersion());
}

@Test
void testBadArtifactId() {
gav.gav = "g:a/x:v";
Assertions.assertThrows(TypeConversionException.class, () -> gav.getArtifactId());
}

@Test
void testBadGroupId() {
gav.gav = "g,x:a:v";
Assertions.assertThrows(TypeConversionException.class, () -> gav.getGroupId());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import java.util.List;
import java.util.Set;
import java.util.function.Predicate;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import org.apache.maven.execution.MavenSession;
Expand Down Expand Up @@ -55,6 +56,8 @@
*/
@Mojo(name = "create", requiresProject = false)
public class CreateProjectMojo extends AbstractMojo {
static final String BAD_IDENTIFIER = "The specified %s identifier (%s) contains invalid characters. Valid characters are alphanumeric (A-Za-z), underscore, dash and dot.";
static final Pattern OK_ID = Pattern.compile("[0-9A-Za-z_.-]+");

private static final String DEFAULT_GROUP_ID = "org.acme";
private static final String DEFAULT_ARTIFACT_ID = "code-with-quarkus";
Expand Down Expand Up @@ -262,6 +265,13 @@ public void execute() throws MojoExecutionException {
}

askTheUserForMissingValues();
if (projectArtifactId != DEFAULT_ARTIFACT_ID && !OK_ID.matcher(projectArtifactId).matches()) {
throw new MojoExecutionException(String.format(BAD_IDENTIFIER, "artifactId", projectArtifactId));
}
if (projectGroupId != DEFAULT_GROUP_ID && !OK_ID.matcher(projectGroupId).matches()) {
throw new MojoExecutionException(String.format(BAD_IDENTIFIER, "groupId", projectGroupId));
}

projectRoot = new File(outputDirectory, projectArtifactId);
if (projectRoot.exists()) {
throw new MojoExecutionException("Unable to create the project, " +
Expand Down
5 changes: 5 additions & 0 deletions docs/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@

<packaging>jar</packaging>
<properties>
<!-- The Graal version we suggest using in documentation - as that's
what we work with by self downloading it: -->
<graal-sdk.version-for-documentation>22.2</graal-sdk.version-for-documentation>
<mandrel.version-for-documentation>22.2</mandrel.version-for-documentation>

<asciidoctor-maven-plugin.version>2.0.0</asciidoctor-maven-plugin.version>
<asciidoctorj-pdf.version>1.5.0-beta.8</asciidoctorj-pdf.version>
<roaster-jdt.version>2.26.0.Final</roaster-jdt.version>
Expand Down
4 changes: 2 additions & 2 deletions docs/src/main/asciidoc/_attributes.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@

:maven-version: ${proposed-maven-version}
:graalvm-version: ${graal-sdk.version-for-documentation}
:graalvm-flavor: ${graal-sdk.version-for-documentation}-java11
:graalvm-flavor: ${graal-sdk.version-for-documentation}-java17
:mandrel-version: ${mandrel.version-for-documentation}
:mandrel-flavor: ${mandrel.version-for-documentation}-java11
:mandrel-flavor: ${mandrel.version-for-documentation}-java17
:surefire-version: ${version.surefire.plugin}
:gradle-version: ${gradle-wrapper.version}
:elasticsearch-version: ${elasticsearch-server.version}
Expand Down
2 changes: 1 addition & 1 deletion docs/src/main/asciidoc/building-native-image.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ You can do so by prepending the flag with `-J` and passing it as additional nati
IMPORTANT: Fully static native executables support is experimental.

On Linux it's possible to package a native executable that doesn't depend on any system shared library.
There are https://www.graalvm.org/22.1/reference-manual/native-image/StaticImages/#preparation[some system requirements] to be fulfilled and additional build arguments to be used along with the `native-image` invocation, a minimum is `-Dquarkus.native.additional-build-args="--static","--libc=musl"`.
There are https://www.graalvm.org/{graalvm-version}/reference-manual/native-image/guides/build-static-executables/#prerequisites-and-preparation[some system requirements] to be fulfilled and additional build arguments to be used along with the `native-image` invocation, a minimum is `-Dquarkus.native.additional-build-args="--static","--libc=musl"`.

Compiling fully static binaries is done by statically linking https://musl.libc.org/[musl] instead of `glibc` and should not be used in production without rigorous testing.

Expand Down
2 changes: 1 addition & 1 deletion docs/src/main/asciidoc/cdi-reference.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ quarkus.arc.exclude-dependency.acme.artifact-id=acme-services <2>
== Native Executables and Private Members

Quarkus is using GraalVM to build a native executable.
One of the limitations of GraalVM is the usage of https://www.graalvm.org/22.2/reference-manual/native-image/Reflection/[Reflection, window="_blank"].
One of the limitations of GraalVM is the usage of https://www.graalvm.org/{graalvm-version}/reference-manual/native-image/Reflection/[Reflection, window="_blank"].
Reflective operations are supported but all relevant members must be registered for reflection explicitly.
Those registrations result in a bigger native executable.

Expand Down
2 changes: 0 additions & 2 deletions docs/src/main/asciidoc/deploying-to-google-cloud.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,6 @@ follow the specific guides for more information on how to develop, package and d

== Deploying to Google App Engine Standard

We will only cover the Java 11 runtime as the Java 8 runtime uses its own Servlet engine which is not compatible with Quarkus.

First, make sure to have an App Engine environment initialized for your Google Cloud project, if not, initialize one via `gcloud app create --project=[YOUR_PROJECT_ID]`.

Then, you will need to create a `src/main/appengine/app.yaml` file, let's keep it minimalistic with only the selected engine:
Expand Down
Loading