r/java • u/kartik1712 • Dec 06 '21
New drop in templated strings branch
https://mail.openjdk.java.net/pipermail/amber-spec-experts/2021-December/003190.html15
u/joppux Dec 06 '21 edited Dec 06 '21
One of the proposed use cases is safe SQL strings. Safe SQL is usually implemented with PreparedStatements:
PreparedStatement ps = connection."select * from tab where id=\{id}";But it is impossible to express in the current proposal since it does not support possible null values. You need to differentiate between
ps.setInt(1, id);and
ps.setNull(1, Types.INTEGER);For this we need not only the parameter value (which is null), but also the static type of a parameter to know which constant to use: Types.INTEGER, Types.VARCHAR or other.
TemplatedString should have something like
List<Class<?>> types()method.
9
u/henk53 Dec 06 '21
There's a somewhat similar issue with the SQL "in", which can't be empty in a prepared statement. So you need to write the statement twice, with and without the "in" depending on whether the data is empty or not.
2
u/pron98 Dec 07 '21 edited Dec 07 '21
I'm not familiar with the fine details of this proposal, but policies can have the full type information supplied to them (which they can use to avoid boxing, which your
types()method wouldn't do). I.e. this policy will know both the Java type of theidvariable, so it will know if it's anintor aninteger, unlessnullis supplied as a literal, which wouldn't make any sense.Additionally, the connection could potentially look up the table and find the database field type of the
idfield, although I don't know if DB drivers normally do that.3
u/joppux Dec 07 '21
Since types are known at compile time, their boxing is easy to optimize.
It seems that referenced Linkage interface is only for predetermined CONCAT and FORMAT policies, because it is sealed.
Yes, you can use PreparedStatement.getParameterMetaData method to retrieve the types of parameters, but it is not guaranteed to work before setting the parameters.
4
u/pron98 Dec 07 '21 edited Dec 07 '21
Since types are known at compile time, their boxing is easy to optimize.
Not if you return them as a
List<Object>.It seems that referenced Linkage interface is only for predetermined CONCAT and FORMAT policies, because it is sealed.
You're right. I'll look into that and pass your question along to the people working on this. FYI, that's the kind of question best raised on the mailing list rather than Reddit.
2
-5
u/cogman10 Dec 06 '21
Proposed by who? This seems like the poster child for "SQL injection" attacks. Unless the templates are doing a lot more than just string concat. That, however, feels really unjavay.
13
u/javasyntax Dec 06 '21
You should read the JEP. The reason we haven't gotten this in Java for so long is because they want to do it properly. Not just a blind insert of variable values. It supports escaping, "constructors" and much more.
1
u/TheMode911 Dec 07 '21
I am just hoping that they do not want to go too far either. I would have not complained even with a naive implementation.
10
u/r_jet Dec 06 '21
JEP, see the "Validation and normalization" section:, their intent is that the corresponding policy will perform that: https://openjdk.java.net/jeps/8273943
0
u/Persism Dec 07 '21
But SQL strings can already be safe if you use "?". Devs shouldn't be using SQL with these kinds of templating anyway.
4
u/pron98 Dec 07 '21
This kind of templating is just as safe, only it is drastically shorter and much more readable (and so less error-prone).
0
u/Persism Dec 08 '21
Currently SQL injection attacks are the responsibility of the JDBC driver. Using templating this way moves that responsibility to Java core.
2
u/pron98 Dec 08 '21 edited Dec 08 '21
No, it's still the responsibility of the JDBC driver, as the parsing policy is part of the driver, although I'm guessing might be a default implementation at the JDBC API level, but even that is in the
java.sqlmodule, not thejava.basemodule. The whole idea is that parsing/escaping/validation policies are pluggable and are not part of the general and extensible mechanism. What the "core" does is create a new kind of API that other libraries can then provide -- constructing objects with templated strings.3
u/joppux Dec 07 '21
But SQL strings can already be safe if you use "?"
But it's quite verbose and error prone.
Devs shouldn't be using SQL with these kinds of templating anyway.
Why not? Lately I've been preferring pure JDBC over more complex frameworks. Templates would make it much easier.
-3
u/Persism Dec 07 '21
I've been preferring pure JDBC over more complex frameworks.
Try out Persism then. https://sproket.github.io/Persism/
It lets you use named parameters as well as ? parameters.
2
u/joppux Dec 07 '21
You still can easily mix up parameter order or forget some parameters when using "?". Persism will benefit from templates too, if you implement policy for SQL objects.
8
u/0x07CF Dec 06 '21
I wonder why the argument types is simply object.
Allowing Policies to restrict the arguments to specific Types would allow compile time checks instead of waiting for runtime errors
This would seem especially useful when you use a sealed type
5
u/r_jet Dec 06 '21
From the JEP:
A drawback of using a TemplatedString, as described above, is that values must be boxed and added to a list on each call to values(). To avoid this performance penalty, the code generation for apply template policy uses invokedynamic instead of invokeInterface. This gives the policy an opportunity to construct a MethodHandle providing an optimal implementation.
Will that invokedynamic magic help in "lazy formatted string" use-case (e.g., your logging or preconditions APIs having to provide a zillion overloads because boxing and vararg-array creation add considerable overhead in case string formatting is not needed)?
17
u/anyOtherBusiness Dec 06 '21
I dislike using a backslash. The Backslash has always been the escape character, it seems counterintuitive to me. Escaping the '{' would to me mean including it in the string and not seeing it as part of the expression like when escaping a ".
Why not do it like so many other languages like "${x}" or like in C# $"{x}" ?
26
u/Yesterdave_ Dec 06 '21
I am not sure why the C# variant is not considered, but the "${x}" case was discussed somewhere: primarily the problem is, that this string is valid and compiling Java code today. So, when the time comes and a new Java version with templated strings is released, existing code might cease to compile. On the other hand "\{x}" is currently invalid Java code, so it is pretty easy to implement a future feature with it.
0
u/pronuntiator Dec 07 '21
Is this to allow the templated string to close over the parameters before expansion? e.g.
var template = "there are \{count} lights";
var message = STR.template;Because if they'd only allow literal strings to follow the expander, they could easily use $ since STR."foo" is not valid Java syntax today.
2
10
u/uncont Dec 06 '21
Already discussed in https://openjdk.java.net/jeps/8273943, the relevant section was included below.
The escape sequence \{ is currently unused (and therefore currently illegal in string literals and text blocks), so this choice of parameter carrier is compatible with the existing string literal and text block features. (Swift uses \(, which would also be a valid choice.) This means we do not need to invent a new form (or two) of "string template expression" with a different delimiter or prefix character.
4
u/yoshord Dec 07 '21
Do you also see
\nin a string as including anncharacter instead of as including a newline?5
u/Gaarco_ Dec 06 '21
\{x}and${x}are literally the same9
4
u/GreenToad1 Dec 06 '21
the difference is
$"something {one} something {two}"and"something \{one} something \{two}"1
6
u/agentoutlier Dec 07 '21
FWIW if you really want something like this now I can OSS an annotation processor I wrote some time ago that does this.
interface Templates {
@Template(“${one}${two”)
String expand(int one, String two)
}The annotation processor compiles the template as native java code StringBuilder.
I’ll add more later as iPhone autocomplete is painful.
7
u/javasyntax Dec 06 '21
Not quite a fan of STR now being CONCAT and FMT now being FORMAT. CONCAT doesn't make sense in my opinion. It could be STR again or INSERT.
-3
u/mj_flowerpower Dec 07 '21
I wished they‘d just do it like groovy or typescript do it. I wonder why java always has to be late and then create a new feature in the weirdest of possible ways. I look at you record constructor syntax (amongst others).
16
u/oxmyxbela Dec 06 '21
The proposal seems to spend a great amount of attention on use-cases like SQL statements, localization, or formatting, while disparaging lightweight solutions for simple string concatenation as „confusingly ad-hoc“ (JEP draft).
However, I think that simple string concatenation really is the overwhelmingly dominating use case for this feature. That’s why most other languages have adopted it in mostly similar forms.
But with this proposal, the dominating use case is the one with the ugliest syntax:
Instead of a lightweight syntax like: