tessl install tessl/maven-io-quarkus--quarkus-qute@3.30.0Offer templating support for web, email, etc in a build time, type-safe way
Qute provides extensive configuration options to customize template processing, validation, debugging, and runtime behavior. All configuration is managed through the quarkus.qute prefix in application.properties and is divided into several categories: general settings, development mode, test mode, and debug settings.
This document covers all available configuration properties, their default values, and practical examples for each setting.
The main configuration interface for Qute is QuteConfig, which provides control over template discovery, validation, character encoding, and content type handling.
@ConfigRoot(phase = ConfigPhase.BUILD_AND_RUN_TIME_FIXED)
@ConfigMapping(prefix = "quarkus.qute")
public interface QuteConfig {
@WithDefault("qute.html,qute.txt,html,txt")
List<String> suffixes();
@ConfigDocMapKey("file-suffix")
Map<String, String> contentTypes();
Optional<List<String>> typeCheckExcludes();
@WithDefault("^\\..*|.*\\/\\..*$")
Pattern templatePathExclude();
@WithDefault("<alias_>")
String iterationMetadataPrefix();
@WithDefault("text/html,text/xml,application/xml,application/xhtml+xml")
List<String> escapeContentTypes();
@WithDefault("UTF-8")
Charset defaultCharset();
@WithDefault("PRIORITIZE")
DuplicitTemplatesStrategy duplicitTemplatesStrategy();
QuteDevModeConfig devMode();
QuteTestModeConfig testMode();
QuteDebugConfig debug();
}The suffixes property defines the list of file extensions that Qute will append when searching for templates. When you call engine.getTemplate("foo"), Qute will look for foo, foo.qute.html, foo.qute.txt, foo.html, and foo.txt in that order.
Default: qute.html,qute.txt,html,txt
Configuration example:
# Use only HTML templates
quarkus.qute.suffixes=html
# Add JSON and XML templates
quarkus.qute.suffixes=qute.html,qute.txt,html,txt,json,xml
# Minimal setup with single suffix
quarkus.qute.suffixes=quteThe contentTypes property maps file suffixes to MIME content types. This is particularly important when working with template variants, as it determines how content is escaped and processed. By default, Qute uses java.net.URLConnection.getFileNameMap() for standard extensions.
Default: Uses Java's built-in file name map
Configuration example:
# Map custom suffixes to content types
quarkus.qute.content-types.yaml=application/x-yaml
quarkus.qute.content-types.yml=application/x-yaml
quarkus.qute.content-types.json=application/json
quarkus.qute.content-types.qute=text/plain
# Override default HTML content type
quarkus.qute.content-types.html=application/xhtml+xmlThe typeCheckExcludes property allows you to intentionally ignore specific properties or methods during type-safe validation. This is useful when you have dynamic properties, reflection-based access, or want to bypass validation for certain patterns.
Format: Each exclusion rule must have at least two parts separated by a dot. The last part matches the property/method name, and preceding parts match the class name. Use * as a wildcard.
Default: None
Configuration example:
# Exclude specific property on a class
quarkus.qute.type-check-excludes=org.acme.Foo.name
# Exclude all properties/methods on a class
quarkus.qute.type-check-excludes=org.acme.Foo.*
# Exclude a property on any class
quarkus.qute.type-check-excludes=*.age
# Multiple exclusions (comma-separated)
quarkus.qute.type-check-excludes=org.acme.User.dynamicField,*.metadata,org.acme.Entity.*
# Exclude reflection-based properties
quarkus.qute.type-check-excludes=*.get,*.set,*.isPattern examples:
org.acme.Foo.name - Excludes the name property/method on org.acme.Fooorg.acme.Foo.* - Excludes all properties/methods on org.acme.Foo*.age - Excludes the age property/method on any classorg.acme.*.id - Excludes id on any class in org.acme packageThe templatePathExclude property is a regular expression that excludes template files from being parsed, validated, or made available at runtime. The pattern matches against the relative file path from the template root, using / as the path separator.
Default: ^\\..*|.*\\/\\..*$ (excludes hidden files starting with a dot)
Configuration example:
# Exclude hidden files (default)
quarkus.qute.template-path-exclude=^\\..*|.*\\/\\..*$
# Exclude backup files
quarkus.qute.template-path-exclude=.*~$|.*\\.bak$
# Exclude specific directories
quarkus.qute.template-path-exclude=.*\\/drafts\\/.*|.*\\/tmp\\/.*
# Exclude test templates in production
quarkus.qute.template-path-exclude=.*\\/test-.*\\.html$
# Complex exclusion pattern
quarkus.qute.template-path-exclude=^\\..*|.*\\/\\..*$|.*\\.backup$|.*\\/wip\\/.*The iterationMetadataPrefix property controls how you access loop metadata (like hasNext, count, index) inside {#for} sections. This affects the syntax used to reference iteration metadata within templates.
Default: <alias_> (alias followed by underscore)
Special constants:
<alias_> - Use alias with underscore: item_hasNext, it_count<alias?> - Use alias with question mark: item?hasNext, it?count<none> - No prefix required: hasNext, countConfiguration example:
# Default: alias with underscore
quarkus.qute.iteration-metadata-prefix=<alias_>
# Use question mark syntax
quarkus.qute.iteration-metadata-prefix=<alias?>
# No prefix (direct access)
quarkus.qute.iteration-metadata-prefix=<none>
# Custom prefix
quarkus.qute.iteration-metadata-prefix=loop_Template usage examples:
With <alias_> (default):
{#for item in items}
{item.name} - Index: {item_index}, HasNext: {item_hasNext}
{/for}With <alias?>:
{#for item in items}
{item.name} - Index: {item?index}, HasNext: {item?hasNext}
{/for}With <none>:
{#for item in items}
{item.name} - Index: {index}, HasNext: {hasNext}
{/for}With custom prefix loop_:
{#for item in items}
{item.name} - Index: {loop_index}, HasNext: {loop_hasNext}
{/for}The escapeContentTypes property defines which MIME types should have characters escaped during rendering. When a template variant matches one of these content types, the characters ', ", <, >, and & are automatically escaped to prevent XSS attacks.
Default: text/html,text/xml,application/xml,application/xhtml+xml
Configuration example:
# Default HTML/XML escaping
quarkus.qute.escape-content-types=text/html,text/xml,application/xml,application/xhtml+xml
# Add SVG to escaped content types
quarkus.qute.escape-content-types=text/html,text/xml,application/xml,application/xhtml+xml,image/svg+xml
# Only escape HTML
quarkus.qute.escape-content-types=text/html
# Disable all escaping (not recommended for production)
quarkus.qute.escape-content-types=The defaultCharset property specifies the character encoding used when reading template files.
Default: UTF-8
Configuration example:
# Default UTF-8 encoding
quarkus.qute.default-charset=UTF-8
# Use ISO-8859-1 for legacy templates
quarkus.qute.default-charset=ISO-8859-1
# Use Windows encoding
quarkus.qute.default-charset=windows-1252The duplicitTemplatesStrategy property determines how Qute handles situations where multiple templates with the same path exist in the application. This commonly occurs when templates are present in multiple JAR files or application archives.
Default: PRIORITIZE
Configuration example:
# Prioritize by archive priority (default)
quarkus.qute.duplicit-templates-strategy=PRIORITIZE
# Fail build on any duplicate
quarkus.qute.duplicit-templates-strategy=FAILThe DuplicitTemplatesStrategy enum defines two approaches for handling duplicate template paths:
public enum DuplicitTemplatesStrategy {
PRIORITIZE,
FAIL
}When PRIORITIZE is set, Qute uses a priority-based resolution system:
Priority levels:
3010Use case: This is the recommended strategy for most applications. It allows library templates to be overridden by application templates while still catching ambiguous situations.
Configuration:
quarkus.qute.duplicit-templates-strategy=PRIORITIZEWhen FAIL is set, the build immediately fails if any duplicate template paths are detected, regardless of priority.
Use case: Use this in strict environments where you want to ensure no template ambiguity exists, or when debugging unexpected template resolution issues.
Configuration:
quarkus.qute.duplicit-templates-strategy=FAILThe QuteRuntimeConfig interface controls runtime behavior of the Qute template engine, including strict rendering, timeout settings, and property-not-found strategies. These settings are in the RUN_TIME configuration phase, separate from the build-time QuteConfig.
@ConfigRoot(phase = ConfigPhase.RUN_TIME)
@ConfigMapping(prefix = "quarkus.qute")
public interface QuteRuntimeConfig {
Optional<PropertyNotFoundStrategy> propertyNotFoundStrategy();
@WithDefault("true")
boolean removeStandaloneLines();
@WithDefault("true")
boolean strictRendering();
@WithDefault("10000")
long timeout();
@WithDefault("true")
boolean useAsyncTimeout();
public enum PropertyNotFoundStrategy {
DEFAULT,
NOOP,
THROW_EXCEPTION,
OUTPUT_ORIGINAL
}
}The propertyNotFoundStrategy property defines how Qute handles standalone expressions that evaluate to a "not found" value at runtime when strictRendering is disabled. This strategy is never used for section parameters (e.g., {#if foo.name}).
Default: DEFAULT in production mode, THROW_EXCEPTION in development mode (when not explicitly specified)
Available strategies:
DEFAULT: Outputs the NOT_FOUND constant to the template outputNOOP: No operation - produces no output for not found valuesTHROW_EXCEPTION: Throws a TemplateException when a value is not foundOUTPUT_ORIGINAL: Outputs the original expression string (e.g., {foo.name})Configuration examples:
# Production: silently ignore missing properties
quarkus.qute.property-not-found-strategy=NOOP
# Development: throw exceptions for better debugging
quarkus.qute.property-not-found-strategy=THROW_EXCEPTION
# Debug mode: output the original expression
quarkus.qute.property-not-found-strategy=OUTPUT_ORIGINAL
# Default behavior (explicit)
quarkus.qute.property-not-found-strategy=DEFAULTUsage example:
// Template: {item.missingProperty}
// With NOOP: renders as ""
// With DEFAULT: renders as "NOT_FOUND"
// With OUTPUT_ORIGINAL: renders as "{item.missingProperty}"
// With THROW_EXCEPTION: throws TemplateExceptionNote: This property is completely ignored when strictRendering is enabled (which is the default).
The removeStandaloneLines property controls whether the parser removes standalone lines from template output. A standalone line contains at least one section tag, parameter declaration, or comment, but no expressions and no non-whitespace characters.
Default: true
Configuration examples:
# Keep standalone lines in output (preserve all whitespace)
quarkus.qute.remove-standalone-lines=false
# Remove standalone lines (default, cleaner output)
quarkus.qute.remove-standalone-lines=trueExample impact:
<!-- Template with removeStandaloneLines=true (default) -->
<ul>
{#for item in items}
<li>{item.name}</li>
{/for}
</ul>
<!-- Output: Clean, no extra blank lines -->
<ul>
<li>Item 1</li>
<li>Item 2</li>
</ul>
<!-- Template with removeStandaloneLines=false -->
<!-- Output: Includes blank lines from {#for} and {/for} lines -->
<ul>
<li>Item 1</li>
<li>Item 2</li>
</ul>The strictRendering property determines whether any expression evaluating to a Results.NotFound value should immediately throw a TemplateException and abort rendering.
Default: true
Configuration examples:
# Strict mode: any not-found value throws exception (recommended)
quarkus.qute.strict-rendering=true
# Lenient mode: use property-not-found-strategy for missing values
quarkus.qute.strict-rendering=falseBehavior:
true (strict mode): Every missing property/method throws a TemplateException
false (lenient mode): Missing properties handled by propertyNotFoundStrategy
Usage example:
// Template: {user.email}
// With strictRendering=true: throws TemplateException if user.email is null or missing
// With strictRendering=false: uses propertyNotFoundStrategy (e.g., outputs "NOT_FOUND" or "")The timeout property sets the global rendering timeout in milliseconds. This timeout is used when no timeout attribute is explicitly set on a TemplateInstance.
Default: 10000 (10 seconds)
Configuration examples:
# Short timeout for fast APIs (5 seconds)
quarkus.qute.timeout=5000
# Longer timeout for complex templates (30 seconds)
quarkus.qute.timeout=30000
# Very short timeout (1 second)
quarkus.qute.timeout=1000
# No timeout (not recommended, use with caution)
quarkus.qute.timeout=0Usage:
// Uses global timeout from configuration
String result = template.data("name", "World").render();
// Override timeout for specific instance
String result = template.instance()
.data("name", "World")
.setTimeout(Duration.ofSeconds(5))
.render();When timeout occurs:
TemplateException is thrownThe useAsyncTimeout property determines whether the global timeout should also apply to asynchronous rendering methods like TemplateInstance.createUni() and TemplateInstance.renderAsync().
Default: true
Configuration examples:
# Apply timeout to async rendering (default)
quarkus.qute.use-async-timeout=true
# Don't apply timeout to async rendering
quarkus.qute.use-async-timeout=falseBehavior:
true: Async methods (createUni(), renderAsync()) respect the global timeoutfalse: Async methods run without timeout constraintsUsage example:
// With useAsyncTimeout=true: times out after global timeout
Uni<String> result = template.instance()
.data("name", "World")
.createUni();
// With useAsyncTimeout=false: no timeout applied
Uni<String> result = template.instance()
.data("name", "World")
.createUni();Complete runtime configuration example:
# Strict mode with short timeout
quarkus.qute.strict-rendering=true
quarkus.qute.timeout=5000
quarkus.qute.use-async-timeout=true
quarkus.qute.remove-standalone-lines=true
# Lenient mode for optional properties
quarkus.qute.strict-rendering=false
quarkus.qute.property-not-found-strategy=NOOP
quarkus.qute.timeout=10000The QuteDevModeConfig interface provides settings specific to development mode (mvn quarkus:dev).
@ConfigGroup
public interface QuteDevModeConfig {
Optional<Pattern> noRestartTemplates();
}The noRestartTemplates property allows you to specify a regular expression pattern for templates that should be hot-reloaded without triggering a full application restart. By default, any template modification triggers a restart to perform build-time validations. Templates matching this pattern are reloaded with only runtime validations.
Default: None (all template changes trigger restart)
Pattern matching: The regex matches against the template path starting from the template root, using / as the path separator (e.g., templates/foo.html).
Configuration example:
# Reload email templates without restart
quarkus.qute.dev-mode.no-restart-templates=templates/emails/.*
# Reload all HTML templates without restart
quarkus.qute.dev-mode.no-restart-templates=.*\\.html$
# Reload templates in specific directories
quarkus.qute.dev-mode.no-restart-templates=templates/(fragments|partials)/.*
# Complex pattern for multiple directories
quarkus.qute.dev-mode.no-restart-templates=templates/(emails|notifications|alerts)/.*\\.html$Benefits:
Trade-offs:
The QuteTestModeConfig interface provides settings for test mode behavior.
@ConfigGroup
public interface QuteTestModeConfig {
@WithDefault("true")
boolean recordRenderedResults();
}The recordRenderedResults property controls whether rendering results from injected and type-safe templates are recorded in a managed RenderedResults bean during tests. This allows tests to inspect what templates were rendered and with what data.
Default: true
Configuration example:
# Enable rendered results recording (default)
quarkus.qute.test-mode.record-rendered-results=true
# Disable recording to improve test performance
quarkus.qute.test-mode.record-rendered-results=falseUsage in tests:
When enabled, you can inject RenderedResults to verify template rendering:
@Inject
RenderedResults results;
@Test
void testTemplateRendering() {
// Trigger template rendering
templateInstance.render();
// Verify rendering occurred
assertFalse(results.getAll().isEmpty());
// Inspect rendered content
String rendered = results.get("email/welcome").data();
assertTrue(rendered.contains("Welcome"));
}Performance consideration: Disable this in performance-intensive test suites where rendering verification is not needed.
The QuteDebugConfig interface controls the Qute debugging capabilities (experimental feature).
@ConfigGroup
public interface QuteDebugConfig {
@WithDefault("true")
boolean enabled();
}The enabled property activates Qute's debug mode, allowing runtime debugging of templates. This is an experimental feature intended for development and troubleshooting.
Default: true
Capabilities when enabled:
Configuration example:
# Enable debug mode (default)
quarkus.qute.debug.enabled=true
# Disable debug mode for production
quarkus.qute.debug.enabled=false
# Disable for performance testing
quarkus.qute.debug.enabled=falseUse cases:
Production consideration: While enabled by default, the debug mode has minimal performance impact when not actively used. However, you may want to explicitly disable it in production builds for security and performance reasons.
Here's a comprehensive example demonstrating all configuration options:
# Template file suffixes
quarkus.qute.suffixes=qute.html,qute.txt,html,txt,json
# Content type mappings
quarkus.qute.content-types.json=application/json
quarkus.qute.content-types.yaml=application/x-yaml
quarkus.qute.content-types.xml=application/xml
# Type-safe validation exclusions
quarkus.qute.type-check-excludes=org.acme.User.dynamicField,*.metadata
# Template path exclusion
quarkus.qute.template-path-exclude=^\\..*|.*\\/\\..*$|.*\\.bak$
# Iteration metadata prefix
quarkus.qute.iteration-metadata-prefix=<alias_>
# Escape content types
quarkus.qute.escape-content-types=text/html,text/xml,application/xml,application/xhtml+xml
# Default character set
quarkus.qute.default-charset=UTF-8
# Duplicate templates strategy
quarkus.qute.duplicit-templates-strategy=PRIORITIZE
# Development mode: hot-reload specific templates
quarkus.qute.dev-mode.no-restart-templates=templates/emails/.*
# Test mode: record rendered results
quarkus.qute.test-mode.record-rendered-results=true
# Debug mode: enable template debugging
quarkus.qute.debug.enabled=trueFor production environments, you might use a minimal configuration:
# Production-optimized settings
quarkus.qute.suffixes=html,txt
quarkus.qute.duplicit-templates-strategy=FAIL
quarkus.qute.debug.enabled=falseFor active development with fast iteration:
# Development-optimized settings
quarkus.qute.suffixes=qute.html,html
quarkus.qute.dev-mode.no-restart-templates=templates/.*
quarkus.qute.debug.enabled=trueFor maximum type safety and validation:
# Strict validation mode
quarkus.qute.duplicit-templates-strategy=FAIL
quarkus.qute.template-path-exclude=^\\..*|.*\\/\\..*$|.*\\/test\\/.*|.*\\.draft$
# Don't exclude any type checks (omit type-check-excludes)Qute configuration is loaded during the BUILD_AND_RUN_TIME_FIXED phase, meaning:
| Property | Default Value | Type |
|---|---|---|
suffixes | qute.html,qute.txt,html,txt | List<String> |
contentTypes | (empty, uses Java's file name map) | Map<String, String> |
typeCheckExcludes | (none) | Optional<List<String>> |
templatePathExclude | ^\\..*|.*\\/\\..*$ | Pattern |
iterationMetadataPrefix | <alias_> | String |
escapeContentTypes | text/html,text/xml,application/xml,application/xhtml+xml | List<String> |
defaultCharset | UTF-8 | Charset |
duplicitTemplatesStrategy | PRIORITIZE | Enum |
devMode.noRestartTemplates | (none) | Optional<Pattern> |
testMode.recordRenderedResults | true | boolean |
debug.enabled | true | boolean |
Configuration values are resolved in this order (highest to lowest precedence):
-Dquarkus.qute.suffixes=html)QUARKUS_QUTE_SUFFIXES=html)application.properties in src/main/resourcesapplication-prod.properties)@WithDefault annotationsYou can override settings per profile:
# Base configuration
quarkus.qute.debug.enabled=true
# Production profile override
%prod.quarkus.qute.debug.enabled=false
%prod.quarkus.qute.duplicit-templates-strategy=FAIL
# Development profile override
%dev.quarkus.qute.dev-mode.no-restart-templates=templates/.*
# Test profile override
%test.quarkus.qute.test-mode.record-rendered-results=trueorg.acme.Foo.name over *.nameSymptom: TemplateException: Template not found
Check:
# Verify suffixes include your template extension
quarkus.qute.suffixes=html,txt
# Check exclusion pattern doesn't match your templates
quarkus.qute.template-path-exclude=^\\..*|.*\\/\\..*$Symptom: Build fails with "Property not found" errors
Solutions:
# Option 1: Add specific exclusion
quarkus.qute.type-check-excludes=org.acme.MyClass.dynamicProperty
# Option 2: Exclude pattern
quarkus.qute.type-check-excludes=*.dynamic*
# Option 3: Disable type checking for specific templates
# (use @CheckedTemplate(requireTypeSafeExpressions = false))Symptom: HTML tags appear as text
Check:
# Verify content type is in escape list
quarkus.qute.escape-content-types=text/html,text/xml
# Verify content type mapping
quarkus.qute.content-types.html=text/htmlSymptom: Templates take too long to render
Solutions:
# Increase timeout
quarkus.qute.timeout=30000
# Or disable timeout for async
quarkus.qute.use-async-timeout=false
# Check for expensive operations in templates
# Move complex logic to Java codeSymptom: Build fails with "Duplicate template" error
Solutions:
# Option 1: Use PRIORITIZE to allow overrides
quarkus.qute.duplicit-templates-strategy=PRIORITIZE
# Option 2: Rename one of the templates
# Option 3: Exclude one template
quarkus.qute.template-path-exclude=.*\\/old-version\\/.*Symptom: Template changes require restart
Check:
# Add pattern to no-restart templates
quarkus.qute.dev-mode.no-restart-templates=templates/ui/.*
# Verify template is in src/main/resources/templates/
# Check file is not excluded by template-path-exclude# application.properties
quarkus.qute.debug.enabled=true
quarkus.qute.dev-mode.no-restart-templates=templates/.*
quarkus.qute.timeout=60000# application-test.properties
quarkus.qute.test-mode.record-rendered-results=true
quarkus.qute.duplicit-templates-strategy=FAIL
quarkus.qute.timeout=5000
quarkus.qute.debug.enabled=false# application-prod.properties
quarkus.qute.debug.enabled=false
quarkus.qute.duplicit-templates-strategy=FAIL
quarkus.qute.timeout=10000
quarkus.qute.use-async-timeout=true
quarkus.qute.strict-rendering=true# application-staging.properties
quarkus.qute.debug.enabled=true
quarkus.qute.duplicit-templates-strategy=PRIORITIZE
quarkus.qute.timeout=15000