Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
35 changes: 29 additions & 6 deletions docs/src/main/asciidoc/qute-reference.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -624,7 +624,7 @@ If you want to use Qute in your Quarkus application add the following dependency
</dependency>
----

In Quarkus, a preconfigured engine instance is provided and available for injection - a bean with scope `@Singleton`, bean type `io.quarkus.qute.Engine` and qualifier `@Default` is registered automatically.
In Quarkus, a preconfigured engine instance is provided and available for injection - a bean with scope `@ApplicationScoped`, bean type `io.quarkus.qute.Engine` and qualifier `@Default` is registered automatically.
Moreover, all templates located in the `src/main/resources/templates` directory are validated and can be easily injected.

[source,java]
Expand All @@ -649,6 +649,29 @@ class MyBean {
<2> The `ResourcePath` qualifier instructs the container to inject a template from a path relative from `src/main/resources/templates`. In this case, the full path is `src/main/resources/templates/detail/items2_v1.html`.
<3> Inject the configured `Engine` instance.

=== Template Variants

Sometimes it's useful to render a specific variant of the template based on the content negotiation.
This can be done by setting a special attribute via `TemplateInstance.setAttribute()`:

[source,java]
----
class MyService {

@Inject
Template items; <1>

@Inject
ItemManager manager;

String renderItems() {
return items.data("items",manager.findItems()).setAttribute(TemplateInstance.SELECTED_VARIANT, new Variant(Locale.getDefault(),"text/html","UTF-8")).render();
}
}
----

NOTE: When using `quarkus-resteasy-qute` the content negotiation is performed automatically. See <<resteasy_integration>>.

=== Injecting Beans Directly In Templates

A CDI bean annotated with `@Named` can be referenced in any template through the `inject` namespace:
Expand Down Expand Up @@ -885,6 +908,7 @@ class Item {
----
<1> The generated value resolver knows how to invoke the `BigDecimal.setScale()` method.

[[resteasy_integration]]
=== RESTEasy Integration

If you want to use Qute in your JAX-RS application, you'll need to add the `quarkus-resteasy-qute` extension first.
Expand Down Expand Up @@ -931,18 +955,17 @@ public class HelloResource {
<2> `Template.data()` returns a new template instance that can be customized before the actual rendering is triggered. In this case, we put the name value under the key `name`. The data map is accessible during rendering.
<3> Note that we don't trigger the rendering - this is done automatically by a special `ContainerResponseFilter` implementation.

==== Variant Templates

Sometimes it could be useful to render a specific variant of the template based on the content negotiation.
`VariantTemplate` is a perfect match for this use case:
The content negotiation is performed automatically.
The resulting output depends on the `Accept` header received from the client.

[source,java]
----
@Path("/detail")
class DetailResource {

@Inject
VariantTemplate item; <1>
Template item; <1>

@GET
@Produces({ MediaType.TEXT_HTML, MediaType.TEXT_PLAIN })
Expand All @@ -952,7 +975,7 @@ class DetailResource {
}
----
<1> Inject a variant template with base path derived from the injected field - `src/main/resources/templates/item`.
<2> The resulting output depends on the `Accept` header received from the client. For `text/plain` the `src/main/resources/templates/item.txt` template is used. For `text/html` the `META-INF/resources/templates/item.html` template is used.
<2> For `text/plain` the `src/main/resources/templates/item.txt` template is used. For `text/html` the `META-INF/resources/templates/item.html` template is used.


=== Development Mode
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
package io.quarkus.mailer.runtime;

import static io.quarkus.qute.api.VariantTemplate.SELECTED_VARIANT;
import static io.quarkus.qute.api.VariantTemplate.VARIANTS;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
Expand All @@ -16,7 +13,6 @@
import io.quarkus.mailer.MailTemplate.MailTemplateInstance;
import io.quarkus.qute.TemplateInstance;
import io.quarkus.qute.Variant;
import io.quarkus.qute.api.VariantTemplate;
import io.smallrye.mutiny.Uni;

class MailTemplateInstanceImpl implements MailTemplate.MailTemplateInstance {
Expand Down Expand Up @@ -89,24 +85,22 @@ public MailTemplateInstance data(String key, Object value) {

@Override
public CompletionStage<Void> send() {
if (templateInstance.getAttribute(VariantTemplate.VARIANTS) != null) {

Object variantsAttr = templateInstance.getAttribute(TemplateInstance.VARIANTS);
if (variantsAttr != null) {
List<Result> results = new ArrayList<>();

@SuppressWarnings("unchecked")
List<Variant> variants = (List<Variant>) templateInstance.getAttribute(VARIANTS);
List<Variant> variants = (List<Variant>) variantsAttr;
for (Variant variant : variants) {
if (variant.mediaType.equals(Variant.TEXT_HTML) || variant.mediaType.equals(Variant.TEXT_PLAIN)) {
results.add(new Result(variant,
Uni.createFrom().completionStage(
() -> templateInstance.setAttribute(SELECTED_VARIANT, variant).data(data).renderAsync())));
() -> templateInstance.setAttribute(TemplateInstance.SELECTED_VARIANT, variant).data(data)
.renderAsync())));
}
}

if (results.isEmpty()) {
throw new IllegalStateException("No suitable template variant found");
}

List<Uni<String>> unis = results.stream().map(Result::getValue).collect(Collectors.toList());
return Uni.combine().all().unis(unis)
.combinedWith(combine(results))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
import org.jboss.logging.Logger;

import io.quarkus.mailer.MailTemplate;
import io.quarkus.qute.Template;
import io.quarkus.qute.api.ResourcePath;
import io.quarkus.qute.api.VariantTemplate;

@Singleton
public class MailTemplateProducer {
Expand All @@ -26,7 +26,7 @@ public class MailTemplateProducer {
MutinyMailerImpl mailer;

@Any
Instance<VariantTemplate> template;
Instance<Template> template;

@Produces
MailTemplate getDefault(InjectionPoint injectionPoint) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,6 @@
import io.quarkus.qute.UserTagSectionHelper;
import io.quarkus.qute.Variant;
import io.quarkus.qute.api.ResourcePath;
import io.quarkus.qute.api.VariantTemplate;
import io.quarkus.qute.deployment.TemplatesAnalysisBuildItem.TemplateAnalysis;
import io.quarkus.qute.deployment.TypeCheckExcludeBuildItem.Check;
import io.quarkus.qute.deployment.TypeInfos.Info;
Expand All @@ -98,7 +97,6 @@
import io.quarkus.qute.runtime.QuteRecorder;
import io.quarkus.qute.runtime.QuteRecorder.QuteContext;
import io.quarkus.qute.runtime.TemplateProducer;
import io.quarkus.qute.runtime.VariantTemplateProducer;
import io.quarkus.qute.runtime.extensions.CollectionTemplateExtensions;
import io.quarkus.qute.runtime.extensions.MapTemplateExtensions;
import io.quarkus.qute.runtime.extensions.NumberTemplateExtensions;
Expand All @@ -108,11 +106,8 @@ public class QuteProcessor {
private static final Logger LOGGER = Logger.getLogger(QuteProcessor.class);

public static final DotName RESOURCE_PATH = DotName.createSimple(ResourcePath.class.getName());

public static final DotName TEMPLATE = DotName.createSimple(Template.class.getName());

public static final DotName VARIANT_TEMPLATE = DotName.createSimple(VariantTemplate.class.getName());

static final DotName ITERABLE = DotName.createSimple(Iterable.class.getName());
static final DotName ITERATOR = DotName.createSimple(Iterator.class.getName());
static final DotName STREAM = DotName.createSimple(Stream.class.getName());
Expand Down Expand Up @@ -164,7 +159,7 @@ void processTemplateErrors(TemplatesAnalysisBuildItem analysis, List<IncorrectEx
AdditionalBeanBuildItem additionalBeans() {
return AdditionalBeanBuildItem.builder()
.setUnremovable()
.addBeanClasses(EngineProducer.class, TemplateProducer.class, VariantTemplateProducer.class, ResourcePath.class,
.addBeanClasses(EngineProducer.class, TemplateProducer.class, ResourcePath.class,
Template.class, TemplateInstance.class, CollectionTemplateExtensions.class,
MapTemplateExtensions.class, NumberTemplateExtensions.class)
.build();
Expand Down Expand Up @@ -682,24 +677,6 @@ void validateTemplateInjectionPoints(QuteConfig config, List<TemplatePathBuildIt
new IllegalStateException("No template found for " + injectionPoint.getTargetInfo())));
}
}

} else if (injectionPoint.getRequiredType().name().equals(VARIANT_TEMPLATE)) {

AnnotationInstance resourcePath = injectionPoint.getRequiredQualifier(RESOURCE_PATH);
String name;
if (resourcePath != null) {
name = resourcePath.value().asString();
} else if (injectionPoint.hasDefaultedQualifier()) {
name = getName(injectionPoint);
} else {
name = null;
}
if (name != null) {
if (filePaths.stream().noneMatch(path -> path.endsWith(name))) {
validationErrors.produce(new ValidationErrorBuildItem(
new IllegalStateException("No variant template found for " + injectionPoint.getTargetInfo())));
}
}
}
}
}
Expand All @@ -721,7 +698,7 @@ TemplateVariantsBuildItem collectTemplateVariants(List<TemplatePathBuildItem> te
variants.add(path);
}
}
LOGGER.debugf("Variant templates found: %s", baseToVariants);
LOGGER.debugf("Template variants found: %s", baseToVariants);
return new TemplateVariantsBuildItem(baseToVariants);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import io.quarkus.qute.Template;
import io.quarkus.qute.TemplateInstance;
import io.quarkus.qute.Variant;
import io.quarkus.qute.api.VariantTemplate;
import io.quarkus.test.QuarkusUnitTest;

public class VariantTemplateTest {
Expand All @@ -31,17 +31,17 @@ public class VariantTemplateTest {
@Test
public void testRendering() {
TemplateInstance rendering = simpleBean.foo.instance().data("bar");
rendering.setAttribute(VariantTemplate.SELECTED_VARIANT, new Variant(null, "text/plain", null));
rendering.setAttribute(TemplateInstance.SELECTED_VARIANT, new Variant(null, "text/plain", null));
assertEquals("bar", rendering.render());
rendering.setAttribute(VariantTemplate.SELECTED_VARIANT, new Variant(null, "text/html", null));
rendering.setAttribute(TemplateInstance.SELECTED_VARIANT, new Variant(null, "text/html", null));
assertEquals("<strong>bar</strong>", rendering.render());
}

@Dependent
public static class SimpleBean {

@Inject
VariantTemplate foo;
Template foo;

}

Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ static Variant guessVariant(String path) {
int suffixIdx = path.lastIndexOf('.');
if (suffixIdx != -1) {
String suffix = path.substring(suffixIdx);
return new Variant(null, VariantTemplateProducer.parseMediaType(suffix), null);
return new Variant(null, TemplateProducer.parseMediaType(suffix), null);
}
return null;
}
Expand Down
Loading