JDK-8296302 : JEP 430: JLS Changes for String Templates (Preview)
  • Type: CSR
  • Component: specification
  • Sub-Component: language
  • Priority: P3
  • Status: Closed
  • Resolution: Approved
  • Fix Versions: 21
  • Submitted: 2022-11-03
  • Updated: 2024-04-12
  • Resolved: 2023-04-25
Related Reports
CSR :  
Relates :  
Relates :  
Relates :  
Description
This is the CSR for the Java Language Specification changes of [JEP-430 String Templates (Preview)](https://bugs.openjdk.java.net/browse/JDK-8273943)

Summary
-------

Enhance the Java programming language with _string templates_. String templates complement Java's existing string literals and text blocks by coupling literal text with embedded expressions and processors to produce specialized results.  This is a [preview language feature and API](http://openjdk.java.net/jeps/12).

Problem
-------

Developers routinely compose strings from a combination of literal text and expressions. Java provides several mechanisms for string composition, though unfortunately all have drawbacks.

- String concatenation with the `+` produces hard-to-read code:

        String s = x + " plus " + y + " equals " + (x + y);

- `StringBuilder` is verbose:

        String s = new StringBuilder()
                     .append(x)
                     .append(" plus ")
                     .append(y)
                     .append(" equals ")
                     .append(x + y)
                     .toString();

- `String::format` and `String::formatted` separate the format string from the parameters, inviting arity and type mismatches:

        String s = String.format("%2$d plus %1$d equals %3$d", x, y, x + y);
        String t = "%2$d plus %1$d equals %3$d".formatted(x, y, x + y);

- `java.text.MessageFormat` requires too much ceremony and uses an unfamiliar syntax in the format string:

        MessageFormat mf = new MessageFormat("{0} plus {1} equals {2}");
        String s = mf.format(x, y, x + y);

The convenience of interpolation also has a downside: It is easy to construct strings that will be interpreted by other systems but which are dangerously incorrect in those systems.

Strings that hold SQL statements, HTML/XML documents, JSON snippets, shell scripts, and natural-language text all need to be validated and sanitized according to domain-specific rules. Since the Java programming language cannot possibly enforce all such rules, it is up to developers using interpolation to validate and sanitize. Typically, this means remembering to wrap embedded expressions in calls to `escape` or `validate` methods, and relying on IDEs or [static analysis tools](https://checkerframework.org/manual/) to help to validate the literal text.

Interpolation is especially dangerous for SQL statements because it can lead to [injection attacks](https://en.wikipedia.org/wiki/SQL_injection). The prevalence of injection attacks as led to organizations dedicated to preventative measures, ex., [OWASP][https://en.wikipedia.org/wiki/OWASP].

Solution
--------

[JEP-430 String Templates (Preview)](https://bugs.openjdk.java.net/browse/JDK-8273943) introduces _string templates_ which will allow users to inject values into a String in situ. The use of string templates versus string interpolation allows for a richer feature that, in addition to composition, allows validation and non-string result transformations.

For the purposes of a terminology overview, the statement;

```
    String s = x + " plus " + y + " equals " + (x + y);
```

can be equivalently expressed using the _template expression_;

```
    String s = STR."\{x} plus \{y} equals \{x + y}";
```

The template expression is composed of two parts, the _template processor_ and the _template argument_ separated with a dot.

The template processor is an expression that when evaluated produces an instance of a class implementing the `ValidatingProcessor` interface. This _processor instance_ receives the details of the template argument by way of the processor's `process` method. The processor uses this method to validate the details of the argument and then produce a result. It is through this `process` method that the string templates feature provides a more secure and richer mechanism than string interpolation.

The automatically imported `STR` template processor used in the example, provides the equivalence of string interpolation.

The template argument can be a string literal, a text block or a _template_. A template has the appearance of a string literal or text block, except the literal's content incorporates one or more _embedded expressions_  distinguished from the literal parts of the content by bracketing with `\{ `and `}`. An embedded expression can be any Java expression.

Once the template argument and embedded expressions are evaluated, the details of the template argument are incorporated into an instance of class that implements the `StringTemplate` interface. The details are represented using two lists, a list of string _fragments_ - the characters outside of the embedded expressions and a list of _values_ - the results of evaluating the embedded expressions.

The template argument details for the example would be a fragments list equivalent to `List.of("", " plus ", " equals ", "")` and values list equivalent to `List.of(x, y, x + y)`. Note that all fragments are provided even if empty.

Further details can be found in the JEP [JEP-430 String Templates (Preview)](https://bugs.openjdk.java.net/browse/JDK-8273943) and the enclosed Java Language Specification edits.

Specification
-------------

Details of the Java Language Specification edits are enclosed.

Changes described above are only available with --enable-preview including the introduction of Template Expressions, new runtime APIs and the automatic import of `java.lang.template.StringTemplate.STR`. No class file changes are required.

Comments
Moving to Approved.
25-04-2023

[~darcy] I've attached the latest spec (2023.03.31) which reflects recent changes to the naming and hierarchy of interfaces used.
31-03-2023

[~darcy]Joe: would you please clarify your last comment. Having a problem parsing the SVOs of this statement.
03-03-2023

[~jlaskey], besides having one or more reviewers, to Finalize the request it should be a form of the change that is intended to be integrated.
02-03-2023

[~darcy] What is the criteria for moving to finalize?
02-03-2023

[~gbierman] and [~jlaskey], thanks for the updates; moving to Provisional.
02-03-2023

[~darcy] Joe: I've done a small amount of surface polishing to the spec following comments on the amber-spec-experts mailing list. No meaningful changes to the detail. Latest spec is attached FYI.
01-03-2023

The new specification simplifies the tokenization of fragments such that tool implementors have more flexibility.
22-02-2023

[~darcy]Updated spec attached.
22-02-2023

Moving to Provisional, not Approved. As a code review comment, I suggest some mechanism to generate warnings about use of "STR" as a field name in earlier source levels, if that is not already implemented (note that I'm not necessarily recommending this be implemented as a current lint warning).
02-02-2023

Thanks [~jlaskey]. Please have these points addressed in the main text of one of the CSRs for the JEP.
07-11-2022

Joe: - STR is only auto imported in preview. - There is some disagreement about this change. I would have preferred to have strings as they exist and then string template expressions with **one** or more embedded expressions. The **one** or more stance doesn't require context sensitivity when scanning quoted tokens, whereas the **zero** or more stance means that the parser has to signal the scanner when in the context of a template process expression. Clever for the spec, not so much for implementors. - No class changes required.
07-11-2022

Some comments/questions after initial readings of the proposed language changes: * Is java.lang.template.StringTemplate.STR auto-imported if preview features are *not* enabled for the latest source? * From the grammar (and as expounded in the JEP text), the "foo" in STR."foo" is a valid string template as the template can have zero or more embedded expressions. I would expect more discussion around this, even just as non-normative explanatory text, in the JLS * I'm inferring there are no class file changes proposed as part of this JEP? No need kinds of constant pool entries, etc.
05-11-2022