Skip to content

Commit

Permalink
Merge branch 'main' into oidc-provider-discord
Browse files Browse the repository at this point in the history
  • Loading branch information
romanziske authored Oct 30, 2023
2 parents 255c9c4 + 3149ece commit b31f72e
Show file tree
Hide file tree
Showing 46 changed files with 1,142 additions and 128 deletions.
3 changes: 2 additions & 1 deletion docs/src/main/asciidoc/building-native-image.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,8 @@ GraalVM {graalvm-version} is required.

1. Install GraalVM if you haven't already. You have a few options for this:
** Download the appropriate archive from <https://github.com/graalvm/mandrel/releases> or <https://github.com/graalvm/graalvm-ce-builds/releases>, and unpack it like you would any other JDK.
** Use platform-specific install tools like https://sdkman.io/jdks#Oracle[sdkman], https://github.com/graalvm/homebrew-tap[homebrew], or https://github.com/ScoopInstaller/Java[scoop].
** Use platform-specific installer tools like https://sdkman.io/jdks#graalce[sdkman], https://github.com/graalvm/homebrew-tap[homebrew], or https://github.com/ScoopInstaller/Java[scoop].
We recommend the _community edition_ of GraalVM. For example, install it with `sdk install java 21-graalce`.
2. Configure the runtime environment. Set `GRAALVM_HOME` environment variable to the GraalVM installation directory, for example:
+
[source,bash]
Expand Down
4 changes: 0 additions & 4 deletions docs/src/main/asciidoc/grpc-getting-started.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -99,10 +99,6 @@ If this retrieved version does not work in your context, you can either force to
You can also download the suitable binary and specify the location via
`-Dquarkus.grpc.protoc-path=/path/to/protoc`.


Alternatively to using the `generate-code` goal of the `quarkus-maven-plugin`, you can use `protobuf-maven-plugin` to generate these files.
See the <<grpc-generation-reference.adoc#protobuf-maven-plugin>> section for more information.

Let's start with a simple _Hello_ service.
Create the `src/main/proto/helloworld.proto` file with the following content:

Expand Down
8 changes: 7 additions & 1 deletion docs/src/main/asciidoc/qute-reference.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -2632,7 +2632,13 @@ WARNING: Unlike with `@Inject` the templates obtained via `RestTemplate` are not

=== Development Mode

In the development mode, all files located in `src/main/resources/templates` are watched for changes and modifications are immediately visible.
In the development mode, all files located in `src/main/resources/templates` are watched for changes.
By default, a template modification results in an application restart that also triggers build-time validations.

However, it's possible to use the `quarkus.qute.dev-mode.no-restart-templates` configuration property to specify the templates for which the application is not restarted.
The configration value is a regular expression that matches the template path relative from the `templates` directory and `/` is used as a path separator.
For example, `quarkus.qute.dev-mode.no-restart-templates=templates/foo.html` matches the template `src/main/resources/templates/foo.html`.
The matching templates are reloaded and only runtime validations are performed.

[[type-safe-message-bundles]]
=== Type-safe Message Bundles
Expand Down
7 changes: 7 additions & 0 deletions docs/src/main/asciidoc/security-jpa.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,13 @@ For applications running in a production environment, do not store passwords as
However, it is possible to store passwords as plain text with the `@Password(PasswordType.CLEAR)` annotation when operating in a test environment.
====

[TIP]
====
The xref:hibernate-orm.adoc#multitenancy[Hibernate Multitenancy] is supported and you can store the user entity in a persistence unit with enabled multitenancy.
However, if your `io.quarkus.hibernate.orm.runtime.tenant.TenantResolver` must access the `io.vertx.ext.web.RoutingContext` to resolve request details, you must disable proactive authentication.
For more information about proactive authentication, please see the Quarkus xref:security-proactive-authentication.adoc[Proactive authentication] guide.
====

include::{generated-dir}/config/quarkus-security-jpa.adoc[opts=optional, leveloffset=+2]

== References
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,15 @@ public class ArcConfig {
@ConfigItem
public ArcContextPropagationConfig contextPropagation;

/**
* If set to {@code true}, the container should try to optimize the contexts for some of the scopes.
* <p>
* Typically, some implementation parts of the context for {@link jakarta.enterprise.context.ApplicationScoped} could be
* pregenerated during build.
*/
@ConfigItem(defaultValue = "true", generateDocumentation = false)
public boolean optimizeContexts;

public final boolean isRemoveUnusedBeansFieldValid() {
return ALLOWED_REMOVE_UNUSED_BEANS_VALUES.contains(removeUnusedBeans.toLowerCase());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,7 @@ public Integer compute(AnnotationTarget target, Collection<StereotypeInfo> stere
}

builder.setBuildCompatibleExtensions(buildCompatibleExtensions.entrypoint);
builder.setOptimizeContexts(arcConfig.optimizeContexts);

BeanProcessor beanProcessor = builder.build();
ContextRegistrar.RegistrationContext context = beanProcessor.registerCustomContexts();
Expand Down Expand Up @@ -516,6 +517,12 @@ public void generateResources(ArcConfig config,
ExecutorService executor = parallelResourceGeneration ? buildExecutor : null;
List<ResourceOutput.Resource> resources;
resources = beanProcessor.generateResources(new ReflectionRegistration() {

@Override
public void registerMethod(String declaringClass, String name, String... params) {
reflectiveMethods.produce(new ReflectiveMethodBuildItem(declaringClass, name, params));
}

@Override
public void registerMethod(MethodInfo methodInfo) {
reflectiveMethods.produce(new ReflectiveMethodBuildItem(methodInfo));
Expand Down Expand Up @@ -591,7 +598,7 @@ public ArcContainerBuildItem initializeContainer(ArcConfig config, ArcRecorder r
throws Exception {
ArcContainer container = recorder.initContainer(shutdown,
currentContextFactory.isPresent() ? currentContextFactory.get().getFactory() : null,
config.strictCompatibility);
config.strictCompatibility, config.optimizeContexts);
return new ArcContainerBuildItem(container);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,13 @@ public class ArcRecorder {
public static volatile Map<String, Function<SyntheticCreationalContext<?>, ?>> syntheticBeanProviders;

public ArcContainer initContainer(ShutdownContext shutdown, RuntimeValue<CurrentContextFactory> currentContextFactory,
boolean strictCompatibility)
boolean strictCompatibility, boolean optimizeContexts)
throws Exception {
ArcContainer container = Arc.initialize(ArcInitConfig.builder()
.setCurrentContextFactory(currentContextFactory != null ? currentContextFactory.getValue() : null)
.setStrictCompatibility(strictCompatibility).build());
ArcInitConfig.Builder builder = ArcInitConfig.builder();
builder.setCurrentContextFactory(currentContextFactory != null ? currentContextFactory.getValue() : null);
builder.setStrictCompatibility(strictCompatibility);
builder.setOptimizeContexts(optimizeContexts);
ArcContainer container = Arc.initialize(builder.build());
shutdown.addShutdownTask(new Runnable() {
@Override
public void run() {
Expand Down
6 changes: 6 additions & 0 deletions extensions/narayana-lra/runtime/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,12 @@
<dependency>
<groupId>org.jboss.narayana.rts</groupId>
<artifactId>lra-proxy-api</artifactId>
<exclusions>
<exclusion>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-client</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.jboss.narayana.rts</groupId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3330,8 +3330,11 @@ private static void produceTemplateBuildItems(BuildProducer<TemplatePathBuildIte
String fullPath = basePath + filePath;
LOGGER.debugf("Produce template build items [filePath: %s, fullPath: %s, originalPath: %s", filePath, fullPath,
originalPath);
// NOTE: we cannot just drop the template because a template param can be added
watchedPaths.produce(new HotDeploymentWatchedFileBuildItem(fullPath, true));
boolean restartNeeded = true;
if (config.devMode.noRestartTemplates.isPresent()) {
restartNeeded = !config.devMode.noRestartTemplates.get().matcher(fullPath).matches();
}
watchedPaths.produce(new HotDeploymentWatchedFileBuildItem(fullPath, restartNeeded));
nativeImageResources.produce(new NativeImageResourceBuildItem(fullPath));
templatePaths.produce(
new TemplatePathBuildItem(filePath, originalPath, readTemplateContent(originalPath, config.defaultCharset)));
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package io.quarkus.qute.deployment.devmode;

import java.util.UUID;

import jakarta.annotation.PostConstruct;
import jakarta.inject.Inject;
import jakarta.inject.Singleton;

import io.quarkus.qute.Template;
import io.quarkus.vertx.web.Route;
import io.vertx.ext.web.RoutingContext;

@Singleton
public class NoRestartRoute {

private String id;

@Inject
Template norestart;

@Route(path = "norestart")
public void test(RoutingContext ctx) {
ctx.end(norestart.data("foo", id).render());
}

@PostConstruct
void init() {
id = UUID.randomUUID().toString();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package io.quarkus.qute.deployment.devmode;

import static io.restassured.RestAssured.given;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;

import org.jboss.shrinkwrap.api.asset.StringAsset;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import io.quarkus.test.QuarkusDevModeTest;
import io.restassured.response.Response;

public class NoRestartTemplatesDevModeTest {

@RegisterExtension
static final QuarkusDevModeTest config = new QuarkusDevModeTest()
.withApplicationRoot(root -> root
.addClass(NoRestartRoute.class)
.addAsResource(new StringAsset(
"Hello {foo}!"),
"templates/norestart.html")
.addAsResource(new StringAsset(
"quarkus.qute.dev-mode.no-restart-templates=templates/norestart.html"),
"application.properties"));

@Test
public void testNoRestartTemplates() {
Response resp = given().get("norestart");
resp.then()
.statusCode(200);
String val = resp.getBody().asString();
assertTrue(val.startsWith("Hello "));

config.modifyResourceFile("templates/norestart.html", t -> t.concat("!!"));

resp = given().get("norestart");
resp.then().statusCode(200);
assertEquals(val + "!!", resp.getBody().asString());
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -88,4 +88,10 @@ public class QuteConfig {
@ConfigItem(defaultValue = "UTF-8")
public Charset defaultCharset;

/**
* Dev mode configuration.
*/
@ConfigItem
public QuteDevModeConfig devMode;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package io.quarkus.qute.runtime;

import java.util.Optional;
import java.util.regex.Pattern;

import io.quarkus.runtime.annotations.ConfigGroup;
import io.quarkus.runtime.annotations.ConfigItem;

@ConfigGroup
public class QuteDevModeConfig {

/**
* By default, a template modification results in an application restart that triggers build-time validations.
* <p>
* This regular expression can be used to specify the templates for which the application is not restarted.
* I.e. the templates are reloaded and only runtime validations are performed.
* <p>
* The matched input is the template path relative from the {@code templates} directory and the
* {@code /} is used as a path separator. For example, {@code templates/foo.html}.
*/
@ConfigItem
public Optional<Pattern> noRestartTemplates;

}
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
package io.quarkus.qute.runtime;

import java.lang.annotation.Annotation;
import java.lang.ref.WeakReference;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
Expand Down Expand Up @@ -32,6 +35,7 @@
import io.quarkus.qute.TemplateInstanceBase;
import io.quarkus.qute.Variant;
import io.quarkus.qute.runtime.QuteRecorder.QuteContext;
import io.quarkus.runtime.LaunchMode;
import io.smallrye.mutiny.Multi;
import io.smallrye.mutiny.Uni;

Expand All @@ -44,7 +48,10 @@ public class TemplateProducer {

private final Map<String, TemplateVariants> templateVariants;

TemplateProducer(Engine engine, QuteContext context, ContentTypes contentTypes) {
// In the dev mode, we need to keep track of injected templates so that we can clear the cached values
private final List<WeakReference<InjectableTemplate>> injectedTemplates;

TemplateProducer(Engine engine, QuteContext context, ContentTypes contentTypes, LaunchMode launchMode) {
this.engine = engine;
Map<String, TemplateVariants> templateVariants = new HashMap<>();
for (Entry<String, List<String>> entry : context.getVariants().entrySet()) {
Expand All @@ -53,6 +60,7 @@ public class TemplateProducer {
templateVariants.put(entry.getKey(), var);
}
this.templateVariants = Collections.unmodifiableMap(templateVariants);
this.injectedTemplates = launchMode == LaunchMode.DEVELOPMENT ? Collections.synchronizedList(new ArrayList<>()) : null;
LOGGER.debugf("Initializing Qute variant templates: %s", templateVariants);
}

Expand All @@ -71,7 +79,7 @@ Template getDefaultTemplate(InjectionPoint injectionPoint) {
LOGGER.warnf("Parameter name not present - using the method name as the template name instead %s", name);
}
}
return new InjectableTemplate(name, templateVariants, engine);
return newInjectableTemplate(name);
}

@Produces
Expand All @@ -87,14 +95,38 @@ Template getTemplate(InjectionPoint injectionPoint) {
if (path == null || path.isEmpty()) {
throw new IllegalStateException("No template location specified");
}
return new InjectableTemplate(path, templateVariants, engine);
return newInjectableTemplate(path);
}

/**
* Used by NativeCheckedTemplateEnhancer to inject calls to this method in the native type-safe methods.
*/
public Template getInjectableTemplate(String path) {
return new InjectableTemplate(path, templateVariants, engine);
return newInjectableTemplate(path);
}

public void clearInjectedTemplates() {
if (injectedTemplates != null) {
synchronized (injectedTemplates) {
for (Iterator<WeakReference<InjectableTemplate>> it = injectedTemplates.iterator(); it.hasNext();) {
WeakReference<InjectableTemplate> ref = it.next();
InjectableTemplate template = ref.get();
if (template == null) {
it.remove();
} else if (template.unambiguousTemplate != null) {
template.unambiguousTemplate.clear();
}
}
}
}
}

private Template newInjectableTemplate(String path) {
InjectableTemplate template = new InjectableTemplate(path, templateVariants, engine);
if (injectedTemplates != null) {
injectedTemplates.add(new WeakReference<>(template));
}
return template;
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package io.quarkus.qute.runtime.devmode;

import java.util.Set;
import java.util.function.Consumer;

import io.quarkus.arc.Arc;
import io.quarkus.dev.spi.HotReplacementContext;
import io.quarkus.dev.spi.HotReplacementSetup;
import io.quarkus.qute.Engine;
import io.quarkus.qute.runtime.TemplateProducer;

public class QuteSetup implements HotReplacementSetup {

@Override
public void setupHotDeployment(HotReplacementContext context) {
context.consumeNoRestartChanges(new Consumer<Set<String>>() {

@Override
public void accept(Set<String> files) {
// Make sure all templates are reloaded
Engine engine = Arc.container().instance(Engine.class).get();
engine.clearTemplates();
TemplateProducer templateProducer = Arc.container().instance(TemplateProducer.class).get();
templateProducer.clearInjectedTemplates();
}
});
}

}
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
io.quarkus.qute.runtime.devmode.QuteErrorPageSetup
io.quarkus.qute.runtime.devmode.QuteErrorPageSetup
io.quarkus.qute.runtime.devmode.QuteSetup
Loading

0 comments on commit b31f72e

Please sign in to comment.