Annotation Interface TemplateExtension


@Retention(RUNTIME) @Target({METHOD,TYPE}) public @interface TemplateExtension

IMPORTANT: This annotation only works in a fully integrated environment; such as a Quarkus application.

Instructs to generate a ValueResolver for a method annotated with this annotation.

If declared on a class a value resolver is generated for every non-private static method declared on the class. Method-level annotations override the behavior defined on the class. Methods that do not meet the following requirements are ignored.

A template extension method:

  • must not be private,
  • must be static,
  • must not return void.
If there is no namespace defined the class of the first parameter that is not annotated with TemplateExtension.TemplateAttribute is used to match the base object. Otherwise the namespace is used to match an expression.
 @TemplateExtension
 static BigDecimal discountedPrice(Item item) {
    // this method matches {item.discountedPrice} if "item" resolves to an object assignable to "Item"
    return item.getPrice().multiply(new BigDecimal("0.9"));
 }
 

Matching by name

By default, the method name is used to match the expression property/method name. However, it is possible to specify the matching name with matchName().
 @TemplateExtension(matchName = "discounted")
 static BigDecimal discountedPrice(Item item) {
    // this method matches {item.discounted} if "item" resolves to an object assignable to "Item"
    return item.getPrice().multiply(new BigDecimal("0.9"));
 }
 
A special constant - ANY - can be used to specify that the extension method matches any name. In this case, an additional string method parameter must be used to pass the property name.
 @TemplateExtension(matchName = "*")
 static String itemProperty(Item item, String name) {
    // this method matches {item.foo} if "item" resolves to an object assignable to "Item"
    // the value of the "name" argument is "foo"
 }
 
It is also possible to match the name against a regular expression specified in matchRegex(). Again, an additional string method parameter must be used to pass the property name.
 @TemplateExtension(matchRegex = "foo|bar")
 static String itemProperty(Item item, String name) {
    // this method matches {item.foo} and {item.bar} if "item" resolves to an object assignable to "Item"
    // the value of the "name" argument is "foo" or "bar"
 }
 
Finally, matchNames() can be used to specify a collection of matching names. An additional string method parameter is mandatory as well.
 @TemplateExtension(matchNames = {"foo", "bar"})
 static String itemProperty(Item item, String name) {
    // this method matches {item.foo} and {item.bar} if "item" resolves to an object assignable to "Item"
    // the value of the "name" argument is "foo" or "bar"
 }
 
Superfluous matching conditions are ignored. The conditions sorted by priority in descending order are: matchRegex(), matchNames() and matchName().
  • Nested Class Summary

    Nested Classes
    Modifier and Type
    Class
    Description
    static @interface 
    Used to annotate a template extension method parameter that should be obtained via TemplateInstance.getAttribute(String).
  • Optional Element Summary

    Optional Elements
    Modifier and Type
    Optional Element
    Description
    If ANY is used then an additional string method parameter must be used to pass the actual property name.
    Note that an additional string method parameter must be used to pass the actual property name.
    Note that an additional string method parameter must be used to pass the actual property name.
    If not empty then a namespace resolver is generated.
    int
    Value resolvers with higher priority take precedence.
  • Field Summary

    Fields
    Modifier and Type
    Field
    Description
    static final String
    Constant value for matchName() indicating that any name matches.
    static final int
    Constant value for {priority().
    static final String
    Constant value for matchName() indicating that the method name should be used.
  • Field Details

  • Element Details

    • matchName

      String matchName
      If ANY is used then an additional string method parameter must be used to pass the actual property name.
      Returns:
      the name is used to match the property name
      Default:
      "<<method name>>"
    • matchNames

      String[] matchNames
      Note that an additional string method parameter must be used to pass the actual property name.
      Returns:
      the list of names used to match the property name
      Default:
      {}
    • matchRegex

      String matchRegex
      Note that an additional string method parameter must be used to pass the actual property name.
      Returns:
      the regex is used to match the property name
      Default:
      ""
    • priority

      int priority
      Value resolvers with higher priority take precedence.

      Keep in mind that the reflection-based value resolver has priority -1 and the max priority value for resolvers generated from TemplateData and type-safe expressions is 10.

      Returns:
      the priority used by the generated value resolver
      See Also:
      Default:
      5
    • namespace

      String namespace
      If not empty then a namespace resolver is generated.

      Multiple extension methods declared on the same class can share the same namespace. However, extension methods declared on different classes cannot share the same namespace.

      It's recommended to specify the priority() if multiple extension methods that share the same namespace also match the same property/method name and parameters.

      Returns:
      the namespace
      See Also:
      Default:
      ""